@findtime/mcp-server 3.25.19 → 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 +44 -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
|
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;
|