@teamso/teamso-mcp 0.0.0-stage → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (112) hide show
  1. package/CHANGELOG.md +121 -0
  2. package/LICENSE +21 -0
  3. package/README.md +516 -2
  4. package/dist/client.d.ts +215 -0
  5. package/dist/client.d.ts.map +1 -0
  6. package/dist/client.js +797 -0
  7. package/dist/client.js.map +1 -0
  8. package/dist/index.d.ts +3 -0
  9. package/dist/index.d.ts.map +1 -0
  10. package/dist/index.js +32 -0
  11. package/dist/index.js.map +1 -0
  12. package/dist/prompts/index.d.ts +12 -0
  13. package/dist/prompts/index.d.ts.map +1 -0
  14. package/dist/prompts/index.js +58 -0
  15. package/dist/prompts/index.js.map +1 -0
  16. package/dist/server.d.ts +28 -0
  17. package/dist/server.d.ts.map +1 -0
  18. package/dist/server.js +58 -0
  19. package/dist/server.js.map +1 -0
  20. package/dist/tools/account.d.ts +4 -0
  21. package/dist/tools/account.d.ts.map +1 -0
  22. package/dist/tools/account.js +34 -0
  23. package/dist/tools/account.js.map +1 -0
  24. package/dist/tools/api.d.ts +13 -0
  25. package/dist/tools/api.d.ts.map +1 -0
  26. package/dist/tools/api.js +980 -0
  27. package/dist/tools/api.js.map +1 -0
  28. package/dist/tools/approvals.d.ts +5 -0
  29. package/dist/tools/approvals.d.ts.map +1 -0
  30. package/dist/tools/approvals.js +120 -0
  31. package/dist/tools/approvals.js.map +1 -0
  32. package/dist/tools/communication.d.ts +4 -0
  33. package/dist/tools/communication.d.ts.map +1 -0
  34. package/dist/tools/communication.js +39 -0
  35. package/dist/tools/communication.js.map +1 -0
  36. package/dist/tools/employees.d.ts +5 -0
  37. package/dist/tools/employees.d.ts.map +1 -0
  38. package/dist/tools/employees.js +113 -0
  39. package/dist/tools/employees.js.map +1 -0
  40. package/dist/tools/help.d.ts +6 -0
  41. package/dist/tools/help.d.ts.map +1 -0
  42. package/dist/tools/help.js +171 -0
  43. package/dist/tools/help.js.map +1 -0
  44. package/dist/tools/index.d.ts +86 -0
  45. package/dist/tools/index.d.ts.map +1 -0
  46. package/dist/tools/index.js +118 -0
  47. package/dist/tools/index.js.map +1 -0
  48. package/dist/tools/leave-support.d.ts +60 -0
  49. package/dist/tools/leave-support.d.ts.map +1 -0
  50. package/dist/tools/leave-support.js +185 -0
  51. package/dist/tools/leave-support.js.map +1 -0
  52. package/dist/tools/leave.d.ts +14 -0
  53. package/dist/tools/leave.d.ts.map +1 -0
  54. package/dist/tools/leave.js +386 -0
  55. package/dist/tools/leave.js.map +1 -0
  56. package/dist/tools/payroll.d.ts +5 -0
  57. package/dist/tools/payroll.d.ts.map +1 -0
  58. package/dist/tools/payroll.js +101 -0
  59. package/dist/tools/payroll.js.map +1 -0
  60. package/dist/tools/performance.d.ts +13 -0
  61. package/dist/tools/performance.d.ts.map +1 -0
  62. package/dist/tools/performance.js +592 -0
  63. package/dist/tools/performance.js.map +1 -0
  64. package/dist/tools/schemas.d.ts +2079 -0
  65. package/dist/tools/schemas.d.ts.map +1 -0
  66. package/dist/tools/schemas.js +460 -0
  67. package/dist/tools/schemas.js.map +1 -0
  68. package/dist/tools/shared.d.ts +20 -0
  69. package/dist/tools/shared.d.ts.map +1 -0
  70. package/dist/tools/shared.js +64 -0
  71. package/dist/tools/shared.js.map +1 -0
  72. package/dist/types.d.ts +545 -0
  73. package/dist/types.d.ts.map +1 -0
  74. package/dist/types.js +7 -0
  75. package/dist/types.js.map +1 -0
  76. package/dist/utils/api-endpoints.d.ts +130 -0
  77. package/dist/utils/api-endpoints.d.ts.map +1 -0
  78. package/dist/utils/api-endpoints.js +459 -0
  79. package/dist/utils/api-endpoints.js.map +1 -0
  80. package/dist/utils/dates.d.ts +27 -0
  81. package/dist/utils/dates.d.ts.map +1 -0
  82. package/dist/utils/dates.js +102 -0
  83. package/dist/utils/dates.js.map +1 -0
  84. package/dist/utils/format.d.ts +8 -0
  85. package/dist/utils/format.d.ts.map +1 -0
  86. package/dist/utils/format.js +26 -0
  87. package/dist/utils/format.js.map +1 -0
  88. package/dist/utils/help-search.d.ts +25 -0
  89. package/dist/utils/help-search.d.ts.map +1 -0
  90. package/dist/utils/help-search.js +93 -0
  91. package/dist/utils/help-search.js.map +1 -0
  92. package/dist/utils/json-schema-dialect.d.ts +12 -0
  93. package/dist/utils/json-schema-dialect.d.ts.map +1 -0
  94. package/dist/utils/json-schema-dialect.js +146 -0
  95. package/dist/utils/json-schema-dialect.js.map +1 -0
  96. package/dist/utils/results.d.ts +27 -0
  97. package/dist/utils/results.d.ts.map +1 -0
  98. package/dist/utils/results.js +88 -0
  99. package/dist/utils/results.js.map +1 -0
  100. package/dist/utils/structured.d.ts +89 -0
  101. package/dist/utils/structured.d.ts.map +1 -0
  102. package/dist/utils/structured.js +307 -0
  103. package/dist/utils/structured.js.map +1 -0
  104. package/dist/utils/text.d.ts +12 -0
  105. package/dist/utils/text.d.ts.map +1 -0
  106. package/dist/utils/text.js +46 -0
  107. package/dist/utils/text.js.map +1 -0
  108. package/dist/version.d.ts +3 -0
  109. package/dist/version.d.ts.map +1 -0
  110. package/dist/version.js +6 -0
  111. package/dist/version.js.map +1 -0
  112. package/package.json +86 -4
package/CHANGELOG.md ADDED
@@ -0,0 +1,121 @@
1
+ # Changelog
2
+
3
+ ## 1.2.0
4
+
5
+ ### Added
6
+
7
+ - Generic API tools that make every Teamso module usable through MCP, always with the token owner's own
8
+ Teamso permissions. They are built on the API's per-user catalog (`/mcp-catalog`), which lists only the
9
+ endpoints the caller may call:
10
+ - `find_api_endpoints` (keywords, module, HTTP method, side effect, paging), `list_api_modules` and
11
+ `describe_api_endpoint` (parameters, body JSON Schema, response kind, SMS-code and side-effect notes,
12
+ example arguments).
13
+ - `call_api_read`: runs only `read` endpoints and sends `X-Teamso-Mcp-Intent: read`, so the API refuses
14
+ anything that writes. JSON results over 40,000 characters are cut with `truncated: true` and paging
15
+ hints; files come back as embedded resources (up to 8 MB).
16
+ - `call_api_write`: returns a preview (resolved request, body validated against the endpoint's JSON Schema
17
+ with ajv 2020-12, delete/SMS warnings, one-line summary) and runs only with `confirm: true`. Handles the
18
+ SMS-code flow (`always`, `conditional`, `preVerify`), plain-text bodies and multipart uploads
19
+ (`files`, base64, 10 MB in total). Ids the catalog does not list for the caller are refused; there are
20
+ no free-form URLs.
21
+ - `request_sms_code`: the generic SMS-code tool (`request_leave_otp` stays as the leave alias).
22
+ - Toolsets: `TEAMSO_TOOLSETS` / the `toolsets` option of `createMcpServer` and `registerTools`
23
+ (`core`, `help`, `leave`, `approvals`, `employees`, `performance`, `communication`, `payroll`, `api`;
24
+ default all). New exports `TOOLSETS`, `TOOLSET_NAMES`, `resolveToolsets`. `TOOL_NAMES` keeps every
25
+ earlier name in the same order; the six new tools are appended.
26
+ - `TeamsoClient`: `listApiEndpoints`, `getApiEndpoint` (cached for a minute), `listApiModules` and
27
+ `callApi`; `MCP_INTENT_HEADER` and `TeamsoResponseTooLargeError` exports.
28
+ - Server instructions explain when to use the generic tools, the preview-then-confirm rule, SMS codes and
29
+ files.
30
+
31
+ ### Changed
32
+
33
+ - `ajv` is now a runtime dependency (request body validation).
34
+
35
+ ### Fixed (found by the local end-to-end run against the real catalog)
36
+
37
+ - Catalog paths with a trailing slash (30 endpoints, e.g. `GET /document/savedQueryListByMe/`,
38
+ `POST /inventory/`, `GET /dashboard-shortcut/`) were refused as "invalid API path". One trailing slash
39
+ is now kept; empty middle segments and dot segments are still refused.
40
+ - Exports sent as `application/octet-stream` (payroll Excel, PDKS records, templates) now carry the type
41
+ of their file name (`.xlsx`, `.pdf`, `.csv`, ...), so clients can open them.
42
+ - `call_api_read` explains Teamso's empty-list answers (`GET_ERROR` / `ITEM_NOT_FOUND` with HTTP 200 and no
43
+ data, e.g. `GET /demand/list` with no demands) as "no matching records" instead of a bare failure.
44
+ - Server instructions map the Turkish words users say to modules ("talep" = the user's own demands, not
45
+ approvals; "masraf"/"harcama" = expenses; "demirbaş"/"zimmet" = inventory, ...).
46
+
47
+ ### Security (review of the generic API tools)
48
+
49
+ - Generic API calls no longer follow HTTP redirects. A 3xx answer is reported as `REDIRECT_NOT_FOLLOWED`
50
+ instead of being fetched, so a redirect can never pull a file from another host (internal addresses
51
+ included) into the conversation. The specific tools are unchanged.
52
+ - Server instructions say that text inside Teamso records is data written by other people, never
53
+ instructions, and that data is changed only for what the user asked.
54
+ - A clear hint for Teamso's new "too many wrong SMS codes" answer: the code is cancelled and a new one is needed.
55
+
56
+ ## 1.1.3
57
+
58
+ ### Fixed
59
+
60
+ - `create_leave_request` said "sent for approval" even when Teamso approved the leave on the spot (no
61
+ approval step for the user); the message now follows the new leave's status.
62
+
63
+ ### Added
64
+
65
+ - `createHelpCache()` and the `helpCache` client option: servers that create a client per request share
66
+ one help bundle cache instead of downloading the bundle on every help tool call.
67
+
68
+ ## 1.1.2
69
+
70
+ ### Added
71
+
72
+ - `TeamsoClient` option `helpPublicUrl` (stdio: `TEAMSO_HELP_PUBLIC_URL`): the public
73
+ site used for every help link and image in tool output. It defaults to
74
+ `helpBaseUrl`, which stays the address the help bundle is downloaded from, so a
75
+ hosted server can download the bundle from an internal mirror (e.g. a loopback
76
+ URL) without that address reaching users.
77
+
78
+ ## 1.1.1
79
+
80
+ ### Fixed
81
+
82
+ - Goal tools showed no evaluation result: `score` was read from the API's legacy
83
+ `score` column, which Teamso leaves empty. Goals now carry `score` (from
84
+ `scoreValue`), `weightedScore`, `finalScore` and `finalScoreText`; goal lists add
85
+ a Score column and the period score (marked "pending approval" until every goal
86
+ of the employee is COMPLETED).
87
+
88
+ ## 1.1.0
89
+
90
+ ### Added
91
+
92
+ - MCP prompts `request_leave` (optional `start`, `end`, `leave_type`, `note`;
93
+ walks `list_leave_types → calculate_leave_days →` confirm `→ request_leave_otp
94
+ → create_leave_request`) and `review_pending_approvals` (no arguments;
95
+ `list_pending_approvals →` ask per request `→ approve_or_reject_leave`).
96
+ - `PROMPT_NAMES` and `registerPrompts` exports, also on the
97
+ `@teamso/teamso-mcp/prompts` subpath; `createMcpServer` registers the prompts.
98
+
99
+ ### Fixed
100
+
101
+ - `list_my_leaves`, `cancel_leave_request` and `create_leave_request` now find
102
+ the caller's leaves: the API puts the owner in `user.id` and leaves `userId`
103
+ null.
104
+ - Goal summaries show the manager's value and the achievement.
105
+
106
+ ## 1.0.0
107
+
108
+ First release.
109
+
110
+ - 28 tools: help center (3), account (1), leave (7), approvals (2), employees (2),
111
+ performance (10), communication (1) and payroll (2).
112
+ - `TeamsoClient` with personal access token auth, Teamso envelope handling
113
+ (HTTP 200 failures become `TeamsoApiError`) and optional trusted-proxy
114
+ caller-IP signing.
115
+ - Typed input and output schemas, annotations, `structuredContent` and
116
+ `nextAction` hints on every tool; JSON Schema 2020-12 on `tools/list`.
117
+ - Write safeguards the API does not enforce on its own: leave decisions only at
118
+ the caller's approval step, goals for others only for direct reports (or
119
+ performance admins), never `approveAndContinue`.
120
+ - Dates stay on Turkey wall clock; API instants are shown in `Europe/Istanbul`.
121
+ - Stdio binary `teamso-mcp`.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Teamso
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,517 @@
1
- # Temporary Holding Version
1
+ <div align="center">
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ # Teamso MCP Server
4
+
5
+ **Official [MCP](https://modelcontextprotocol.io/) server for [Teamso](https://teamso.com/)** — request leave, handle approvals, find colleagues, manage performance goals, read payslips, search the Teamso help center and reach every other Teamso module through permission-checked generic API tools, from Cursor, Claude, Windsurf, and any MCP-compatible AI assistant.
6
+
7
+ [![npm](https://img.shields.io/badge/npm-@teamso/teamso--mcp-1a56db?style=for-the-badge&logo=npm&logoColor=white)](https://www.npmjs.com/package/@teamso/teamso-mcp)
8
+ [![MCP](https://img.shields.io/badge/MCP-compatible-333?style=for-the-badge)](https://modelcontextprotocol.io/)
9
+ [![MIT](https://img.shields.io/badge/license-MIT-6f42c1?style=for-the-badge)](./LICENSE)
10
+
11
+ [Official MCP Server](https://teamso.com/docs/teamso-mcp-server) · [Self-Hosted MCP](https://teamso.com/docs/mcp-self-hosted) · [Access Tokens](https://teamso.com/dashboard/mcp-access) · [Help Center](https://help.teamso.com/) · [Teamso](https://teamso.com/)
12
+
13
+ </div>
14
+
15
+ ## Quick Start
16
+
17
+ Local `npx` and library usage require Node.js 20 or later. The hosted MCP
18
+ endpoint does not require a local Node.js installation.
19
+
20
+ ### 1. Create an Access Token
21
+
22
+ Sign in to Teamso and create a personal access token at
23
+ [teamso.com/dashboard/mcp-access](https://teamso.com/dashboard/mcp-access).
24
+ The token starts with `tms_pat_` and is shown only once.
25
+
26
+ ### 2. Add to Your AI Assistant
27
+
28
+ **Cursor** — open MCP settings (`Cmd+Shift+P` → "Open MCP settings") and add:
29
+
30
+ ```json
31
+ {
32
+ "mcpServers": {
33
+ "teamso": {
34
+ "command": "npx",
35
+ "args": ["-y", "@teamso/teamso-mcp"],
36
+ "env": {
37
+ "TEAMSO_ACCESS_TOKEN": "tms_pat_your-token"
38
+ }
39
+ }
40
+ }
41
+ }
42
+ ```
43
+
44
+ **Claude Code:**
45
+
46
+ ```bash
47
+ claude mcp add teamso -e TEAMSO_ACCESS_TOKEN=tms_pat_your-token -- npx -y @teamso/teamso-mcp
48
+ ```
49
+
50
+ Or connect to the hosted server without installing anything:
51
+
52
+ ```bash
53
+ claude mcp add --transport http teamso https://mcp.teamso.com/v1 \
54
+ --header "Authorization: Bearer tms_pat_your-token"
55
+ ```
56
+
57
+ **Claude Desktop** — add to `claude_desktop_config.json`:
58
+
59
+ ```json
60
+ {
61
+ "mcpServers": {
62
+ "teamso": {
63
+ "type": "stdio",
64
+ "command": "npx",
65
+ "args": ["-y", "@teamso/teamso-mcp"],
66
+ "env": {
67
+ "TEAMSO_ACCESS_TOKEN": "tms_pat_your-token"
68
+ }
69
+ }
70
+ }
71
+ }
72
+ ```
73
+
74
+ **Windsurf** — add to `~/.codeium/windsurf/mcp_config.json`:
75
+
76
+ ```json
77
+ {
78
+ "mcpServers": {
79
+ "teamso": {
80
+ "command": "npx",
81
+ "args": ["-y", "@teamso/teamso-mcp"],
82
+ "env": {
83
+ "TEAMSO_ACCESS_TOKEN": "tms_pat_your-token"
84
+ }
85
+ }
86
+ }
87
+ }
88
+ ```
89
+
90
+ **Other clients** — any client that supports Streamable HTTP can use the hosted
91
+ server with a bearer header:
92
+
93
+ ```json
94
+ {
95
+ "mcpServers": {
96
+ "teamso": {
97
+ "url": "https://mcp.teamso.com/v1",
98
+ "headers": {
99
+ "Authorization": "Bearer tms_pat_your-token"
100
+ }
101
+ }
102
+ }
103
+ }
104
+ ```
105
+
106
+ Stdio-only clients can run `npx -y @teamso/teamso-mcp` with
107
+ `TEAMSO_ACCESS_TOKEN` in its environment.
108
+
109
+ ### 3. Start Using
110
+
111
+ Ask your AI assistant:
112
+
113
+ - *"How many leave days do I have left?"*
114
+ - *"Request annual leave from 2 to 4 November"*
115
+ - *"Which leave requests are waiting for my approval?"*
116
+ - *"Who is Can Öztürk's manager?"*
117
+ - *"Show my goals for Q4 2026 and send the drafts for approval"*
118
+ - *"Open my September payslip"*
119
+ - *"Teamso'da performans hedefi nasıl girilir?"*
120
+
121
+ ## Authentication
122
+
123
+ Every tool runs as the owner of the personal access token, with exactly the
124
+ roles and permissions that user has in Teamso. A tool the user may not use in
125
+ the web app fails with a clear permission message here too.
126
+
127
+ - Create, list and revoke tokens at [teamso.com/dashboard/mcp-access](https://teamso.com/dashboard/mcp-access).
128
+ - Tokens of deactivated users stop working immediately; revoked or expired tokens return `401`.
129
+ - If your company restricts Teamso to an IP allowlist, requests from `npx`
130
+ come from your own IP address and must be allowed.
131
+ - Creating or cancelling a leave request needs an SMS code, exactly like the
132
+ web app: `request_leave_otp` sends it, and the user reads it back to the
133
+ assistant. Each SMS uses company digital credit.
134
+ - Token management, password, security settings and API key endpoints cannot
135
+ be called with a personal access token.
136
+ - The generic API tools only list and call the endpoints the token owner's own
137
+ Teamso permissions allow: a user without the leave-add permission cannot add
138
+ leave through MCP either.
139
+
140
+ ```
141
+ TEAMSO_ACCESS_TOKEN=tms_pat_your-token
142
+ ```
143
+
144
+ ## Available Tools
145
+
146
+ ### Help center
147
+
148
+ | Tool | Description |
149
+ |------|-------------|
150
+ | `search_help_articles` | Search the Teamso user guides (Turkish-insensitive, Turkish suffixes stripped) by query, language, module and role |
151
+ | `get_help_article` | Read one guide as Markdown with steps, common problems and related articles |
152
+ | `list_help_modules` | Browse the modules that have guides and their article ids |
153
+
154
+ ### Account
155
+
156
+ | Tool | Description |
157
+ |------|-------------|
158
+ | `get_me` | Your profile: name, email, company, department, position, manager, roles and permission codes |
159
+
160
+ ### Leave
161
+
162
+ | Tool | Description |
163
+ |------|-------------|
164
+ | `list_leave_types` | Leave types you can request, with remaining days and per-type rules |
165
+ | `get_my_leave_balance` | Remaining leave days per type |
166
+ | `calculate_leave_days` | Working days, return-to-work date and Teamso's pre-check for a planned leave |
167
+ | `request_leave_otp` | Send the SMS code needed to create or cancel a leave request (valid 3 minutes) |
168
+ | `create_leave_request` | Create a leave request with the SMS code and send it for approval |
169
+ | `list_my_leaves` | Your leave requests with status, filterable by dates and status |
170
+ | `cancel_leave_request` | Cancel one of your leave requests with the SMS code |
171
+
172
+ ### Approvals
173
+
174
+ | Tool | Description |
175
+ |------|-------------|
176
+ | `list_pending_approvals` | Leave requests waiting for your decision |
177
+ | `approve_or_reject_leave` | Approve, or reject with a reason, a leave request at your approval step |
178
+
179
+ ### Employees
180
+
181
+ | Tool | Description |
182
+ |------|-------------|
183
+ | `search_employees` | Find active colleagues by name or email |
184
+ | `get_employee_profile` | A colleague's branch, department, position, manager and contact details |
185
+
186
+ ### Performance
187
+
188
+ | Tool | Description |
189
+ |------|-------------|
190
+ | `list_performance_periods` | Periods with dates, target-entry window and evaluation scale |
191
+ | `list_my_goals` | Your goals in a period and whether you can add more |
192
+ | `list_team_goals` | Goals of the employees you manage, with what you can approve |
193
+ | `create_user_goal` | Create a personal goal for yourself or a direct report (performance admins: anyone) |
194
+ | `send_goals_to_approval` | Send your draft goals to your manager |
195
+ | `approve_goal` | Approve a goal waiting for you |
196
+ | `revise_and_approve_goal` | Change a goal's title, details, weight or target and approve it |
197
+ | `update_goal_actual_value` | Enter the achieved value of your goal during evaluation |
198
+ | `update_manager_actual_value` | Enter your assessment of an employee's goal as their manager |
199
+ | `approve_goal_evaluation` | Approve an employee's evaluation for a period |
200
+
201
+ ### Communication
202
+
203
+ | Tool | Description |
204
+ |------|-------------|
205
+ | `list_announcements` | Latest company and shuttle announcements |
206
+
207
+ ### Payroll
208
+
209
+ | Tool | Description |
210
+ |------|-------------|
211
+ | `list_my_payslips` | Your e-payslips by term with status |
212
+ | `get_payslip_pdf` | One payslip as an embedded `application/pdf` resource |
213
+
214
+ ### Whole system: generic API tools
215
+
216
+ | Tool | Description |
217
+ |------|-------------|
218
+ | `list_api_modules` | Teamso modules with how many API endpoints you can call in each |
219
+ | `find_api_endpoints` | Search the endpoints you may call by keywords, module, HTTP method or side effect |
220
+ | `describe_api_endpoint` | Parameters, body JSON Schema, response kind, SMS-code and side-effect notes, example arguments |
221
+ | `call_api_read` | Run a read-only endpoint; returns JSON (long lists are cut with `truncated: true`) or a file |
222
+ | `call_api_write` | Preview, then (with `confirm: true`) run an endpoint that creates, changes or deletes data |
223
+ | `request_sms_code` | Send the SMS code an endpoint needs (`request_leave_otp` is the leave-specific alias) |
224
+
225
+ Leave chain:
226
+ `list_leave_types → calculate_leave_days → request_leave_otp → create_leave_request`
227
+
228
+ Approval chain:
229
+ `list_pending_approvals → approve_or_reject_leave`
230
+
231
+ Goal chain:
232
+ `list_performance_periods → list_my_goals → create_user_goal → send_goals_to_approval`
233
+
234
+ Everything else (expenses, overtime, time tracking, payroll, recruiting,
235
+ inventory, documents, settings...):
236
+ `find_api_endpoints → describe_api_endpoint → call_api_read` or
237
+ `call_api_write (preview) → user confirms → call_api_write confirm: true`
238
+
239
+ ## Whole system: generic API tools
240
+
241
+ The specific tools above cover the most common tasks. Every other Teamso
242
+ module is reachable through six generic tools built on the Teamso API's
243
+ per-user catalog (`GET /mcp-catalog/endpoints`, `/endpoint`, `/modules`):
244
+
245
+ - **Only what you may use.** The catalog evaluates each endpoint's permission
246
+ rule for the token owner, so `find_api_endpoints` lists only endpoints the
247
+ user may call, and `describe_api_endpoint` / `call_api_*` refuse every id the
248
+ catalog does not list for that user. There are no free-form URLs: a call is
249
+ always an endpoint id (`"POST /expense-form"`) plus `path_params`, `query`
250
+ and `body`, and the real request still passes Teamso's own permission checks.
251
+ Login, password, token, security-setting, payment and SMS endpoints are never
252
+ listed.
253
+ - **Reads are read-only.** `call_api_read` only runs endpoints whose
254
+ `sideEffect` is `read` and sends `X-Teamso-Mcp-Intent: read`, with which the
255
+ API refuses anything that would write (403). `GET` endpoints that do change
256
+ data (`read_with_writes`) must go through `call_api_write`.
257
+ - **Writes preview first.** `call_api_write` without `confirm` sends nothing:
258
+ it returns the resolved request, the body checked against the endpoint's JSON
259
+ Schema (ajv, 2020-12; errors listed), delete and SMS warnings and a one-line
260
+ summary. The assistant shows it to the user and repeats the call with
261
+ `confirm: true` only after the user agrees. Invalid requests are never sent.
262
+ - **SMS codes.** Endpoints with `smsCodeRequired: always` (or `preVerify`) need
263
+ `otp_code` (`request_sms_code` sends it; the code is verified immediately
264
+ before the call). `conditional` endpoints are called first; when Teamso
265
+ answers `OTP_NOT_DONE` the given `otp_code` is verified and the call retried
266
+ once, otherwise the tool asks for `request_sms_code`.
267
+ - **Files.** File responses (PDF, Excel, CSV, images) come back as an embedded
268
+ resource with `mimeType` and file name, up to 8 MB; larger files fail with a
269
+ clear message. Multipart endpoints take `files: [{field, filename,
270
+ content_type, base64}]`, up to 10 files and 10 MB in total.
271
+ - **Large results.** JSON results above 40,000 characters are cut to the
272
+ items that fit, with `truncated: true` and a `truncation` object (original
273
+ and returned item counts, how to page). Results are never cut silently.
274
+ - **Errors.** Teamso failures, including HTTP 200 responses with a failure
275
+ `message_code`, come back as `isError` results naming the `message_code`.
276
+
277
+ ```text
278
+ find_api_endpoints { "query": "masraf", "side_effect": "write" }
279
+ describe_api_endpoint { "id": "POST /expense-form/{expenseFormId}/finalize" }
280
+ call_api_write { "id": "POST /expense-form/{expenseFormId}/finalize", "path_params": { "expenseFormId": "…" } } → preview
281
+ request_sms_code {} → user reads the code
282
+ call_api_write { …same arguments…, "confirm": true, "otp_code": "123456" } → runs it
283
+ ```
284
+
285
+ ### Toolsets
286
+
287
+ `TEAMSO_TOOLSETS` (or the `toolsets` option of `createMcpServer`) limits the
288
+ tools a server offers, as a comma-separated list. Default: all tools.
289
+
290
+ | Toolset | Tools |
291
+ |---------|-------|
292
+ | `core` | `get_me` |
293
+ | `help` | `search_help_articles`, `get_help_article`, `list_help_modules` |
294
+ | `leave` | `list_leave_types`, `get_my_leave_balance`, `calculate_leave_days`, `request_leave_otp`, `create_leave_request`, `list_my_leaves`, `cancel_leave_request` |
295
+ | `approvals` | `list_pending_approvals`, `approve_or_reject_leave` |
296
+ | `employees` | `search_employees`, `get_employee_profile` |
297
+ | `performance` | the ten goal and evaluation tools |
298
+ | `communication` | `list_announcements` |
299
+ | `payroll` | `list_my_payslips`, `get_payslip_pdf` |
300
+ | `api` | `find_api_endpoints`, `list_api_modules`, `describe_api_endpoint`, `call_api_read`, `call_api_write`, `request_sms_code` |
301
+
302
+ An unknown toolset name stops the server with the list of valid names.
303
+
304
+ ```json
305
+ "env": {
306
+ "TEAMSO_ACCESS_TOKEN": "tms_pat_...",
307
+ "TEAMSO_TOOLSETS": "core,leave,approvals,api"
308
+ }
309
+ ```
310
+
311
+ ## Prompts
312
+
313
+ The server also publishes MCP prompts: ready-made starting points that clients
314
+ show as slash commands or prompt pickers (`prompts/list`, `prompts/get`). A
315
+ prompt only steers the assistant through the tools above; every write still
316
+ needs the user's confirmation and, for leave requests, the SMS code.
317
+
318
+ | Prompt | Arguments | Description |
319
+ |--------|-----------|-------------|
320
+ | `request_leave` | `start`, `end`, `leave_type`, `note` (all optional) | Create a leave request: `list_leave_types → calculate_leave_days →` confirm with the user `→ request_leave_otp → create_leave_request`. Missing dates are asked for; `end` defaults to `start`, `leave_type` to annual leave |
321
+ | `review_pending_approvals` | — | Go through the leave requests waiting for your approval: `list_pending_approvals →` ask the user about each request `→ approve_or_reject_leave` |
322
+
323
+ Relative dates such as *"tomorrow"* / *"yarın"* are resolved in Turkey time
324
+ (`Europe/Istanbul`).
325
+
326
+ ### LLM-friendly responses
327
+
328
+ All tools publish typed MCP input and output schemas (JSON Schema 2020-12) and
329
+ annotations (`readOnlyHint`, `destructiveHint`, `idempotentHint`,
330
+ `openWorldHint`). Successful calls return `structuredContent` for reliable
331
+ chaining and concise Markdown `content` for clients that only render text.
332
+ Failures return `isError: true` with an explanation the assistant can act on
333
+ (for example: ask for a new SMS code, or which permission is missing).
334
+
335
+ Teamso reports many failures with HTTP 200 and `code: 1` (for example
336
+ `OTP_NOT_DONE`, `ITEM_NOT_FOUND`, `CREDIT_INSUFFICIENT`). The client checks
337
+ `message_code` and turns those into errors, so a tool never reports success
338
+ for a request Teamso refused.
339
+
340
+ When the next step needs another tool, the response includes an executable
341
+ `nextAction`:
342
+
343
+ ```json
344
+ {
345
+ "request": {
346
+ "leaveTypeId": "lt-annual",
347
+ "leaveTypeName": "Yıllık İzin",
348
+ "start": "2026-11-02 09:00",
349
+ "end": "2026-11-04 18:00",
350
+ "workingDays": 3,
351
+ "returnToWorkDate": "2026-11-05 09:00"
352
+ },
353
+ "remainingDays": 14,
354
+ "remainingAfterRequest": 11,
355
+ "canRequest": true,
356
+ "problems": [],
357
+ "nextAction": {
358
+ "tool": "request_leave_otp",
359
+ "arguments": {},
360
+ "reason": "Creating the request needs an SMS code. After the user confirms these days, send the code, then call create_leave_request with the same leave_type_id, start, end and the otp_code."
361
+ }
362
+ }
363
+ ```
364
+
365
+ Dates are Turkey local time. Leave dates accept `yyyy-MM-dd` (the leave starts
366
+ at your shift start and ends at your shift end, 09:00–18:00 by default) or
367
+ `yyyy-MM-dd HH:mm`. Goal and filter dates are `yyyy-MM-dd`.
368
+
369
+ Write tools never skip Teamso's approval chain, and `approve_or_reject_leave`
370
+ only decides requests that are at your own approval step. `create_user_goal`
371
+ only creates goals for other people when they report to you directly, or when
372
+ you have the performance administrator permission.
373
+
374
+ The access token is sent only to the Teamso API. It is never written to logs or
375
+ error messages, and the help tools download the public help bundle without it.
376
+
377
+ ## Hosted MCP Server
378
+
379
+ Teamso also provides a hosted MCP server at `https://mcp.teamso.com/v1` that
380
+ requires no local installation. It serves the same tools and prompts, plus
381
+ Teamso's content tools that run inside the Teamso API. See the
382
+ [MCP Server documentation](https://teamso.com/docs/teamso-mcp-server) for setup
383
+ instructions.
384
+
385
+ ## Documentation
386
+
387
+ - [MCP Server (Hosted)](https://teamso.com/docs/teamso-mcp-server) — setup guides for Cursor, Claude Code, Claude Desktop, Windsurf and other clients
388
+ - [Self-Hosted MCP](https://teamso.com/docs/mcp-self-hosted) — run locally with npx, environment variables, library usage
389
+ - [Access Tokens](https://teamso.com/dashboard/mcp-access) — create and revoke personal access tokens
390
+ - [Help Center](https://help.teamso.com/) — the user guides behind the help tools
391
+
392
+ ## Using as a Library
393
+
394
+ This package exports its core components for use in custom MCP servers:
395
+
396
+ ```typescript
397
+ import { TeamsoClient } from '@teamso/teamso-mcp/client';
398
+ import { createMcpServer } from '@teamso/teamso-mcp/server';
399
+
400
+ const client = new TeamsoClient('tms_pat_your-token');
401
+ const server = createMcpServer(client);
402
+ ```
403
+
404
+ A server that forwards end users' requests can sign the caller's IP so Teamso
405
+ applies the company IP allowlist and audit log to the real caller. The secret
406
+ must match the API's `security.mcp-proxy.shared-secret`:
407
+
408
+ ```typescript
409
+ const client = new TeamsoClient(userToken, 'https://api.teamso.com/v1', {
410
+ trustedProxy: { clientIp: request.ip, sharedSecret: process.env.TEAMSO_MCP_PROXY_SECRET! },
411
+ });
412
+ ```
413
+
414
+ ### Exports
415
+
416
+ | Export | Description |
417
+ |--------|-------------|
418
+ | `createMcpServer(client, options?)` | Creates an McpServer with all 34 tools and both prompts registered; `options` sets `name`, `version`, `instructions` and `toolsets` |
419
+ | `TeamsoClient` | Teamso REST client (personal access token, envelope handling, optional trusted-proxy signing) |
420
+ | `TeamsoApiError` | Error with `status`, `messageCode`, `apiMessage` and the response `body` |
421
+ | `registerTools(server, client, options?)` | Register the tools (optionally only some `toolsets`) on an existing McpServer |
422
+ | `TOOL_NAMES` | Names of the tools this package serves, for routing other names elsewhere |
423
+ | `TOOLSETS`, `TOOLSET_NAMES`, `resolveToolsets(selection)` | Tool groups for `TEAMSO_TOOLSETS` and the tools a selection serves |
424
+ | `MCP_INTENT_HEADER` | `X-Teamso-Mcp-Intent`; with value `read` the API refuses requests that would write |
425
+ | `TeamsoResponseTooLargeError` | Thrown by `TeamsoClient.callApi` when a response exceeds its size limit |
426
+ | `registerPrompts(server)` | Register the prompts on an existing McpServer |
427
+ | `PROMPT_NAMES` | Names of the prompts this package serves (`request_leave`, `review_pending_approvals`) |
428
+ | `withJsonSchema2020_12(transport)` | Rewrites `tools/list` schemas to JSON Schema 2020-12 on any transport |
429
+ | `signProxyRequest(input)` | The trusted-proxy signature, for verifiers and tests |
430
+ | `VERSION` | Package version |
431
+
432
+ ```typescript
433
+ // Import specific components
434
+ import { TeamsoClient, TeamsoApiError } from '@teamso/teamso-mcp/client';
435
+ import { registerTools, TOOL_NAMES } from '@teamso/teamso-mcp/tools';
436
+ import { registerPrompts, PROMPT_NAMES } from '@teamso/teamso-mcp/prompts';
437
+ ```
438
+
439
+ ## Environment Variables
440
+
441
+ | Variable | Required | Description |
442
+ |----------|----------|-------------|
443
+ | `TEAMSO_ACCESS_TOKEN` | Yes | Your personal access token (`tms_pat_...`) |
444
+ | `TEAMSO_API_BASE_URL` | No | Override the API base URL (default: `https://api.teamso.com/v1`) |
445
+ | `TEAMSO_HELP_BASE_URL` | No | Site the help articles are downloaded from (default: `https://teamso.com`) |
446
+ | `TEAMSO_HELP_PUBLIC_URL` | No | Public site used for help links and images in tool output (default: `TEAMSO_HELP_BASE_URL`). Set it when the download address is internal |
447
+ | `TEAMSO_TOOLSETS` | No | Comma-separated toolsets to serve: `core`, `help`, `leave`, `approvals`, `employees`, `performance`, `communication`, `payroll`, `api` (default: all) |
448
+
449
+ ## Self-hosting from source
450
+
451
+ ```bash
452
+ git clone https://github.com/Teamsocom/Teamso-MCP.git
453
+ cd Teamso-MCP
454
+ npm ci
455
+ npm run build
456
+ TEAMSO_ACCESS_TOKEN=tms_pat_your-token node dist/index.js
457
+ ```
458
+
459
+ Point your client at the build instead of `npx`:
460
+
461
+ ```json
462
+ {
463
+ "mcpServers": {
464
+ "teamso": {
465
+ "command": "node",
466
+ "args": ["/absolute/path/to/Teamso-MCP/dist/index.js"],
467
+ "env": {
468
+ "TEAMSO_ACCESS_TOKEN": "tms_pat_your-token"
469
+ }
470
+ }
471
+ }
472
+ }
473
+ ```
474
+
475
+ The package builds itself on install (`prepare`), so it can also be installed
476
+ straight from GitHub: `npm install github:Teamsocom/Teamso-MCP#v1.1.3`.
477
+
478
+ Run the tests (mocked API, no network) with `npm test`.
479
+
480
+ ## Releasing
481
+
482
+ 1. Bump `version` in `package.json`, add a `CHANGELOG.md` entry, commit and push.
483
+ 2. Tag `v<version>` and create a GitHub release from it: `.github/workflows/publish.yml` type-checks,
484
+ tests, builds and runs `npm publish --provenance --access public`.
485
+ 3. An existing tag can be published by hand: `gh workflow run publish.yml -f tag=v1.1.3`.
486
+
487
+ Authentication is npm trusted publishing (OIDC) once it is configured for `@teamso/teamso-mcp` on
488
+ npmjs.com; until then the `NPM_TOKEN` repository secret (an automation token of the `@teamso` npm
489
+ organization) is used.
490
+
491
+ ## Links
492
+
493
+ - [Teamso](https://teamso.com)
494
+ - [MCP Server documentation](https://teamso.com/docs/teamso-mcp-server)
495
+ - [Self-hosted MCP documentation](https://teamso.com/docs/mcp-self-hosted)
496
+ - [npm package](https://www.npmjs.com/package/@teamso/teamso-mcp)
497
+ - [GitHub repository](https://github.com/Teamsocom/Teamso-MCP)
498
+ - [Changelog](./CHANGELOG.md)
499
+
500
+ ## Contributing
501
+
502
+ Issues and pull requests are welcome: see [CONTRIBUTING.md](CONTRIBUTING.md). Report security problems
503
+ privately as described in [SECURITY.md](SECURITY.md).
504
+
505
+ ## License
506
+
507
+ MIT — see [LICENSE](./LICENSE) for details.
508
+
509
+ ---
510
+
511
+ <div align="center">
512
+
513
+ **Built by the Teamso team**
514
+
515
+ [teamso.com](https://teamso.com) · [GitHub @Teamsocom](https://github.com/Teamsocom)
516
+
517
+ </div>