@findtime/mcp-server 3.25.18 → 3.25.20
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.
- package/README.md +25 -5
- package/SKILL.md +71 -0
- package/package.json +1 -1
- package/server.js +30 -0
package/README.md
CHANGED
|
@@ -49,9 +49,12 @@ Optional environment variables:
|
|
|
49
49
|
- `FINDTIME_TIME_API_BASE_URL`
|
|
50
50
|
- `TIME_API_BASE_URL`
|
|
51
51
|
- `TIME_API_TIMEOUT_MS`
|
|
52
|
+
- `FINDTIME_BINDING_TYPE` for optional install/workspace binding context. Supported values: `slack_team`, `workspace_id`, `install_id`.
|
|
53
|
+
- `FINDTIME_BINDING_VALUE` for the install/workspace identifier that matches the selected binding type.
|
|
54
|
+
- `FINDTIME_BINDING_HEADER` to override the header name directly for custom enterprise environments.
|
|
55
|
+
- `FINDTIME_MCP_CLIENT_ID` or `FINDTIME_MCP_INSTALL_ID` to provide a stable client identifier. If omitted, the server creates one locally under the user's state directory. When present, the MCP wrapper forwards it to `time-api` as `X-Findtime-User-ID` for enterprise usage attribution.
|
|
52
56
|
- `FINDTIME_MCP_CLIENT_TYPE`
|
|
53
57
|
- `FINDTIME_MCP_TOOL_MODE=answer-only` to expose only `answer_time_question`, `get_findtime_help`, and `get_api_diagnostics` for enterprise bots that should route every natural-language request through the answer API.
|
|
54
|
-
- `FINDTIME_MCP_CLIENT_ID` or `FINDTIME_MCP_INSTALL_ID` to provide a stable client identifier. If omitted, the server creates one locally under the user's state directory.
|
|
55
58
|
- `FINDTIME_MCP_INSTRUMENTATION_ENABLED=false` to opt out of anonymous usage telemetry.
|
|
56
59
|
- `FINDTIME_MCP_USAGE_TELEMETRY_URL` to override the default telemetry endpoint.
|
|
57
60
|
|
|
@@ -86,6 +89,9 @@ enabled = true
|
|
|
86
89
|
FINDTIME_MCP_CLIENT_TYPE = "codex"
|
|
87
90
|
FINDTIME_TIME_API_BASE_URL = "https://time-api.findtime.io"
|
|
88
91
|
FINDTIME_TIME_API_KEY = "YOUR_FINDTIME_SECRET_KEY"
|
|
92
|
+
# Optional enterprise install binding:
|
|
93
|
+
# FINDTIME_BINDING_TYPE = "workspace_id"
|
|
94
|
+
# FINDTIME_BINDING_VALUE = "YOUR_WORKSPACE_ID"
|
|
89
95
|
```
|
|
90
96
|
|
|
91
97
|
### Claude Desktop
|
|
@@ -99,13 +105,13 @@ FINDTIME_TIME_API_KEY = "YOUR_FINDTIME_SECRET_KEY"
|
|
|
99
105
|
"findtime": {
|
|
100
106
|
"command": "npx",
|
|
101
107
|
"args": ["-y", "@findtime/mcp-server"],
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
108
|
+
"env": {
|
|
109
|
+
"FINDTIME_TIME_API_BASE_URL": "https://time-api.findtime.io",
|
|
110
|
+
"FINDTIME_TIME_API_KEY": "YOUR_FINDTIME_SECRET_KEY"
|
|
111
|
+
}
|
|
105
112
|
}
|
|
106
113
|
}
|
|
107
114
|
}
|
|
108
|
-
}
|
|
109
115
|
```
|
|
110
116
|
|
|
111
117
|
### Claude CLI / Claude Code
|
|
@@ -138,6 +144,20 @@ If your Claude CLI uses JSON config instead, add:
|
|
|
138
144
|
}
|
|
139
145
|
```
|
|
140
146
|
|
|
147
|
+
For enterprise installs, the minimum credential is always the API key. If the install environment has a stable workspace or installation identifier, optionally add:
|
|
148
|
+
|
|
149
|
+
```text
|
|
150
|
+
FINDTIME_BINDING_TYPE=workspace_id
|
|
151
|
+
FINDTIME_BINDING_VALUE=YOUR_WORKSPACE_ID
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
For Slack-specific installs:
|
|
155
|
+
|
|
156
|
+
```text
|
|
157
|
+
FINDTIME_BINDING_TYPE=slack_team
|
|
158
|
+
FINDTIME_BINDING_VALUE=T01ABC123
|
|
159
|
+
```
|
|
160
|
+
|
|
141
161
|
## Verify installation
|
|
142
162
|
|
|
143
163
|
Use an explicit tool-call prompt first:
|
package/SKILL.md
CHANGED
|
@@ -70,6 +70,50 @@ When packaging instructions for another agent, include this `SKILL.md` file with
|
|
|
70
70
|
|
|
71
71
|
For a company bot or server-side agent, set `FINDTIME_MCP_CLIENT_TYPE` to a stable identifier such as `company-bot`, and provide a stable install ID with `FINDTIME_MCP_CLIENT_ID` or `FINDTIME_MCP_INSTALL_ID` when possible.
|
|
72
72
|
|
|
73
|
+
For enterprise installs, always try to provide a stable caller identifier.
|
|
74
|
+
|
|
75
|
+
How to pass it:
|
|
76
|
+
|
|
77
|
+
- if you control the MCP wrapper config, set `FINDTIME_MCP_INSTALL_ID` or `FINDTIME_MCP_CLIENT_ID`; the wrapper forwards that value to `time-api.findtime.io` as `X-Findtime-User-ID`
|
|
78
|
+
- if you control direct HTTP calls to `time-api.findtime.io`, send the same value explicitly in the `X-Findtime-User-ID` header
|
|
79
|
+
- if you also have a stable thread or conversation identifier, send it as `X-Findtime-Conversation-ID`
|
|
80
|
+
|
|
81
|
+
Use this for enterprise usage attribution.
|
|
82
|
+
|
|
83
|
+
Example MCP wrapper config:
|
|
84
|
+
|
|
85
|
+
```text
|
|
86
|
+
FINDTIME_TIME_API_KEY=your_enterprise_api_key
|
|
87
|
+
FINDTIME_MCP_CLIENT_TYPE=enterprise-bot
|
|
88
|
+
FINDTIME_MCP_INSTALL_ID=install_12345
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
With that config, the MCP wrapper calls `time-api.findtime.io` using:
|
|
92
|
+
|
|
93
|
+
```text
|
|
94
|
+
X-API-Key: your_enterprise_api_key
|
|
95
|
+
X-Findtime-User-ID: install_12345
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Direct HTTP example when you are not using the MCP wrapper:
|
|
99
|
+
|
|
100
|
+
```text
|
|
101
|
+
GET /api/time/current?query=Tokyo
|
|
102
|
+
Authorization: Bearer <your_enterprise_api_key>
|
|
103
|
+
X-Findtime-User-ID: install_12345
|
|
104
|
+
X-Findtime-Conversation-ID: thread_abc
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
Use the most stable first-party identifier you have:
|
|
108
|
+
|
|
109
|
+
- preferred: a true per-user ID from your platform or agent runtime
|
|
110
|
+
- next best: a stable conversation or thread ID when the same user may appear across multiple sessions
|
|
111
|
+
- next best: your platform's install ID or deployment ID
|
|
112
|
+
- fallback: your platform's stable workspace or tenant ID
|
|
113
|
+
- last resort: a stable agent client ID
|
|
114
|
+
|
|
115
|
+
If no true per-user ID is available, it is acceptable for `X-Findtime-User-ID` to carry an install ID or other stable caller identity instead of a human end-user ID.
|
|
116
|
+
|
|
73
117
|
For enterprise bots that should avoid model-level tool selection across the lower-level APIs, set:
|
|
74
118
|
|
|
75
119
|
```text
|
|
@@ -122,6 +166,33 @@ When using `findtime.io` MCP:
|
|
|
122
166
|
- Mention DST only when relevant to the user's question or when it explains an offset difference.
|
|
123
167
|
- Keep answers concise unless the user asks for details.
|
|
124
168
|
|
|
169
|
+
## Voice
|
|
170
|
+
|
|
171
|
+
Use a calm, practical, time-aware voice when presenting `findtime.io` MCP results.
|
|
172
|
+
|
|
173
|
+
- Lead with the exact answer first: time, date, timezone, offset, or recommended meeting window.
|
|
174
|
+
- Add useful human context when it matters, such as tomorrow/yesterday, early morning, late evening, overnight, weekend, or outside working hours.
|
|
175
|
+
- Be lightly opinionated about awkward meeting times. Call out who pays the scheduling cost.
|
|
176
|
+
- Keep humor subtle and brief. Personality should make the answer easier to use, not less precise.
|
|
177
|
+
- Never let voice obscure the source facts, uncertainty, ambiguity, timezone ID, local date, offset, or DST status.
|
|
178
|
+
- If the tool returns ambiguity or a clarification request, preserve that first and do not guess for the sake of sounding helpful.
|
|
179
|
+
|
|
180
|
+
Good style:
|
|
181
|
+
|
|
182
|
+
```text
|
|
183
|
+
3:00 PM in New York on Tuesday is 8:00 PM in London and 5:00 AM Wednesday in Tokyo.
|
|
184
|
+
|
|
185
|
+
London gets an easy evening slot. Tokyo crosses into the next morning, so that one is only friendly for very early risers.
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
Meeting style:
|
|
189
|
+
|
|
190
|
+
```text
|
|
191
|
+
Best fit: 8:00 AM San Francisco / 5:00 PM Berlin / 1:00 AM Sydney.
|
|
192
|
+
|
|
193
|
+
That works cleanly for San Francisco and Berlin, but Sydney takes the late-night hit. If Sydney needs sane hours, rotate the burden or move this async.
|
|
194
|
+
```
|
|
195
|
+
|
|
125
196
|
## Failure Policy
|
|
126
197
|
|
|
127
198
|
If the `findtime.io` MCP server is configured but a tool call fails:
|
package/package.json
CHANGED
package/server.js
CHANGED
|
@@ -48,6 +48,18 @@ const DEFAULT_API_KEY = firstNonEmpty(
|
|
|
48
48
|
process.env.FINDTIME_MCP_API_KEY,
|
|
49
49
|
process.env.FINDTIME_TIME_API_KEY
|
|
50
50
|
);
|
|
51
|
+
const DEFAULT_BINDING_TYPE = firstNonEmpty(
|
|
52
|
+
process.env.FINDTIME_BINDING_TYPE,
|
|
53
|
+
process.env.FINDTIME_MCP_BINDING_TYPE
|
|
54
|
+
) || '';
|
|
55
|
+
const DEFAULT_BINDING_VALUE = firstNonEmpty(
|
|
56
|
+
process.env.FINDTIME_BINDING_VALUE,
|
|
57
|
+
process.env.FINDTIME_MCP_BINDING_VALUE
|
|
58
|
+
) || '';
|
|
59
|
+
const DEFAULT_BINDING_HEADER = firstNonEmpty(
|
|
60
|
+
process.env.FINDTIME_BINDING_HEADER,
|
|
61
|
+
process.env.FINDTIME_MCP_BINDING_HEADER
|
|
62
|
+
) || '';
|
|
51
63
|
const TIMEZONE_HELPERS_PATH = path.join(REPO_ROOT, 'slack-bot', 'timezone-helpers.js');
|
|
52
64
|
const ANSWER_ONLY_TOOL_NAMES = new Set(['answer_time_question', 'get_findtime_help', 'get_api_diagnostics']);
|
|
53
65
|
|
|
@@ -1048,6 +1060,9 @@ function createFindtimeMcpServer(options = {}) {
|
|
|
1048
1060
|
const apiBaseUrl = options.apiBaseUrl || DEFAULT_API_BASE_URL;
|
|
1049
1061
|
const timeoutMs = Number.isFinite(options.timeoutMs) ? options.timeoutMs : DEFAULT_TIMEOUT_MS;
|
|
1050
1062
|
const apiKey = options.apiKey === undefined ? DEFAULT_API_KEY : options.apiKey;
|
|
1063
|
+
const bindingType = options.bindingType === undefined ? DEFAULT_BINDING_TYPE : options.bindingType;
|
|
1064
|
+
const bindingValue = options.bindingValue === undefined ? DEFAULT_BINDING_VALUE : options.bindingValue;
|
|
1065
|
+
const bindingHeader = options.bindingHeader === undefined ? DEFAULT_BINDING_HEADER : options.bindingHeader;
|
|
1051
1066
|
const serverName = options.serverName || 'findtime';
|
|
1052
1067
|
const serverTitle = options.serverTitle || 'findtime Time API MCP';
|
|
1053
1068
|
const resolveLocationImpl = options.resolveLocationImpl === undefined
|
|
@@ -1079,6 +1094,13 @@ function createFindtimeMcpServer(options = {}) {
|
|
|
1079
1094
|
headers.Authorization = `Bearer ${apiKey.trim()}`;
|
|
1080
1095
|
}
|
|
1081
1096
|
|
|
1097
|
+
const resolvedBindingHeader = typeof bindingHeader === 'string' && bindingHeader.trim()
|
|
1098
|
+
? bindingHeader.trim()
|
|
1099
|
+
: normalizeBindingHeader(bindingType);
|
|
1100
|
+
if (resolvedBindingHeader && typeof bindingValue === 'string' && bindingValue.trim()) {
|
|
1101
|
+
headers[resolvedBindingHeader] = bindingValue.trim();
|
|
1102
|
+
}
|
|
1103
|
+
|
|
1082
1104
|
const controller = new AbortController();
|
|
1083
1105
|
const timeout = setTimeout(() => controller.abort(), timeoutMs);
|
|
1084
1106
|
|
|
@@ -1403,6 +1425,14 @@ function createFindtimeMcpServer(options = {}) {
|
|
|
1403
1425
|
};
|
|
1404
1426
|
}
|
|
1405
1427
|
|
|
1428
|
+
function normalizeBindingHeader(bindingType) {
|
|
1429
|
+
const normalized = String(bindingType || '').trim().toLowerCase();
|
|
1430
|
+
if (normalized === 'slack_team') return 'X-Slack-Team-ID';
|
|
1431
|
+
if (normalized === 'workspace_id') return 'X-Findtime-Workspace-ID';
|
|
1432
|
+
if (normalized === 'install_id') return 'X-Findtime-Install-ID';
|
|
1433
|
+
return '';
|
|
1434
|
+
}
|
|
1435
|
+
|
|
1406
1436
|
function tryParseJson(value) {
|
|
1407
1437
|
if (typeof value !== 'string' || !value.trim()) {
|
|
1408
1438
|
return undefined;
|