@thalovant/mcp-server 0.1.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.
package/.env.example ADDED
@@ -0,0 +1,49 @@
1
+ # Local stdio defaults.
2
+ THALOVANT_PROFILE=prod
3
+ THALOVANT_API_URL=https://api.thalovant.com
4
+
5
+ # Use one control-plane auth option for private/admin tools.
6
+ # THALOVANT_ACCESS_TOKEN=
7
+ # THALOVANT_EMAIL=
8
+ # THALOVANT_PASSWORD=
9
+
10
+ # Runtime identity options for local stdio usage.
11
+ # THALOVANT_ACCESS_KEY=
12
+ # THALOVANT_PASSWORD=
13
+ # THALOVANT_SITE_ID=
14
+ # THALOVANT_DEFAULT_MASTER=
15
+ # THALOVANT_HUB_WSS_HOST=
16
+ # THALOVANT_HUB_HTTPS_HOST=
17
+
18
+ # Streamable HTTP transport.
19
+ MCP_TRANSPORT=http
20
+ MCP_HTTP_HOST=127.0.0.1
21
+ MCP_HTTP_PORT=3000
22
+ MCP_PUBLIC_URL=http://127.0.0.1:3000
23
+ MCP_HTTP_ALLOWED_HOSTS=127.0.0.1:3000,localhost:3000
24
+ MCP_HTTP_ALLOWED_ORIGINS=
25
+ MCP_HTTP_AUTH_TOKEN=
26
+
27
+ # Production remote auth: prefer jwt or introspection over static tokens.
28
+ # MCP_HTTP_AUTH_MODE=jwt
29
+ # MCP_OAUTH_ISSUER=https://auth.example.com/
30
+ # MCP_OAUTH_JWKS_URL=https://auth.example.com/.well-known/jwks.json
31
+ # MCP_OAUTH_AUDIENCE=https://mcp.example.com/mcp
32
+ # MCP_OAUTH_AUTHORIZATION_SERVERS=https://auth.example.com/
33
+ # MCP_OAUTH_REQUIRED_SCOPES=mcp:thalovant
34
+
35
+ # MCP_HTTP_AUTH_MODE=introspection
36
+ # MCP_OAUTH_INTROSPECTION_URL=https://auth.example.com/oauth2/introspect
37
+ # MCP_OAUTH_CLIENT_ID=
38
+ # MCP_OAUTH_CLIENT_SECRET=
39
+
40
+ # Multi-user remote deployments should map each MCP principal to Thalovant credentials.
41
+ # THALOVANT_PRINCIPAL_CREDENTIALS_FILE=/run/secrets/thalovant-principals.json
42
+ # THALOVANT_PRINCIPAL_CREDENTIALS_DIR=/run/secrets/thalovant-principals
43
+ # THALOVANT_ALLOW_SHARED_CREDENTIALS=false
44
+
45
+ # Optional policy and audit controls.
46
+ # MCP_TOOL_ALLOWLIST=thalovant_*
47
+ # MCP_TOOL_DENYLIST=thalovant_delete_memory_item
48
+ # MCP_AUDIT_LOG=stderr
49
+ # MCP_AUDIT_LOG_FILE=/var/log/thalovant-mcp/audit.jsonl
package/CHANGELOG.md ADDED
@@ -0,0 +1,14 @@
1
+ # Changelog
2
+
3
+ ## 0.1.0
4
+
5
+ - Initial public MCP server for Thalovant.
6
+ - Added stdio transport for local MCP hosts.
7
+ - Added Streamable HTTP transport for remote MCP clients.
8
+ - Added static bearer, JWT/JWKS, and OAuth introspection auth modes.
9
+ - Added protected resource metadata discovery.
10
+ - Added per-principal Thalovant credential isolation.
11
+ - Added tool allow/deny policy.
12
+ - Added structured audit logging.
13
+ - Added in-memory and file-backed event storage.
14
+ - Added Docker, Compose, Kubernetes, CI, registry metadata, smoke tests, and benchmarks.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Thalovant
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 ADDED
@@ -0,0 +1,288 @@
1
+ # Thalovant MCP Server
2
+
3
+ Public-ready MCP server for Thalovant control-plane and hub runtime APIs.
4
+
5
+ It uses the official Thalovant Node.js SDK and the production MCP TypeScript SDK over stdio and Streamable HTTP, so it works with local MCP hosts such as Claude Desktop, Codex, Cursor, and remote MCP clients.
6
+
7
+ ## What It Includes
8
+
9
+ - stdio transport for local agents.
10
+ - Streamable HTTP transport at `/mcp` for remote agents.
11
+ - OAuth-style protected resource metadata at `/.well-known/oauth-protected-resource`.
12
+ - Static bearer tokens for simple/private deployments.
13
+ - JWT/JWKS and OAuth token introspection for production remote deployments.
14
+ - Per-principal Thalovant credentials and tool policy.
15
+ - Host/origin validation, CORS, rate limiting, body limits, secure headers, and session binding.
16
+ - Optional resumability event storage and JSONL audit logs.
17
+ - Docker, Compose, Kubernetes, CI, npm package metadata, and MCP registry `server.json`.
18
+
19
+ ## Why TypeScript
20
+
21
+ Thalovant publishes SDKs for Python, Node.js, Go, and Rust. This server uses Node.js because `@thalovant/sdk` directly exposes the Thalovant control plane, identity loading, WSS/HTTPS/MQTT runtime clients, memory, analytics, and context helpers, while `@modelcontextprotocol/sdk` is the best-supported path for cross-agent stdio and Streamable HTTP servers.
22
+
23
+ ## Install
24
+
25
+ ```bash
26
+ npm install
27
+ npm run build
28
+ ```
29
+
30
+ Node.js 20 or newer is required.
31
+
32
+ ## Local Stdio
33
+
34
+ Public hub discovery does not need Thalovant credentials. Private control-plane tools and runtime hub tools read credentials only from the MCP server environment or server-side principal credential files. Do not pass API tokens or passwords through chat or tool arguments.
35
+
36
+ ```bash
37
+ export THALOVANT_ACCESS_TOKEN="..."
38
+ # or
39
+ export THALOVANT_EMAIL="you@example.com"
40
+ export THALOVANT_PASSWORD="..."
41
+
42
+ export THALOVANT_PROFILE="prod"
43
+ export THALOVANT_API_URL="https://api.thalovant.com"
44
+
45
+ npm start
46
+ ```
47
+
48
+ The server speaks MCP over stdio and does not write logs to stdout.
49
+
50
+ Runtime hub tools load local identities in this order:
51
+
52
+ 1. `identityFile` tool argument.
53
+ 2. `configPath` or `profile` tool argument.
54
+ 3. Thalovant SDK environment identity variables.
55
+ 4. The default Thalovant SDK config profile.
56
+
57
+ Keep Thalovant identity files secret. The SDK expects protected config files such as `~/.config/thalovant/config.yaml` with mode `0600`.
58
+
59
+ ## Streamable HTTP
60
+
61
+ Remote mode uses MCP Streamable HTTP at `/mcp` and requires bearer authentication by default.
62
+
63
+ ```bash
64
+ export MCP_TRANSPORT="http"
65
+ export MCP_HTTP_HOST="127.0.0.1"
66
+ export MCP_HTTP_PORT="3000"
67
+ export MCP_HTTP_AUTH_TOKEN="$(openssl rand -hex 32)"
68
+ export MCP_HTTP_ALLOWED_HOSTS="127.0.0.1:3000,localhost:3000"
69
+
70
+ npm run start:http
71
+ ```
72
+
73
+ Clients connect to:
74
+
75
+ ```text
76
+ http://127.0.0.1:3000/mcp
77
+ Authorization: Bearer <token>
78
+ ```
79
+
80
+ Health checks are available at `/healthz` and `/readyz`.
81
+
82
+ For public deployments, set the public URL and exact host/origin allowlists:
83
+
84
+ ```bash
85
+ export MCP_HTTP_HOST="0.0.0.0"
86
+ export MCP_HTTP_PORT="3000"
87
+ export MCP_PUBLIC_URL="https://mcp.example.com"
88
+ export MCP_HTTP_ALLOWED_HOSTS="mcp.example.com"
89
+ export MCP_HTTP_ALLOWED_ORIGINS="https://agent.example.com"
90
+ ```
91
+
92
+ ## Remote Auth
93
+
94
+ Use static bearer tokens only for local, private, or single-tenant deployments:
95
+
96
+ ```bash
97
+ export MCP_HTTP_AUTH_TOKEN="$(openssl rand -hex 32)"
98
+ # or
99
+ export MCP_HTTP_AUTH_TOKENS="token-a,token-b"
100
+ ```
101
+
102
+ Use JWT/JWKS for production resource-server validation:
103
+
104
+ ```bash
105
+ export MCP_HTTP_AUTH_MODE="jwt"
106
+ export MCP_OAUTH_ISSUER="https://auth.example.com/"
107
+ export MCP_OAUTH_JWKS_URL="https://auth.example.com/.well-known/jwks.json"
108
+ export MCP_OAUTH_AUDIENCE="https://mcp.example.com/mcp"
109
+ export MCP_OAUTH_AUTHORIZATION_SERVERS="https://auth.example.com/"
110
+ export MCP_OAUTH_REQUIRED_SCOPES="mcp:thalovant"
111
+ ```
112
+
113
+ Use introspection when your authorization server issues opaque tokens:
114
+
115
+ ```bash
116
+ export MCP_HTTP_AUTH_MODE="introspection"
117
+ export MCP_OAUTH_INTROSPECTION_URL="https://auth.example.com/oauth2/introspect"
118
+ export MCP_OAUTH_CLIENT_ID="mcp-server-client"
119
+ export MCP_OAUTH_CLIENT_SECRET="..."
120
+ export MCP_OAUTH_AUDIENCE="https://mcp.example.com/mcp"
121
+ export MCP_OAUTH_AUTHORIZATION_SERVERS="https://auth.example.com/"
122
+ export MCP_OAUTH_REQUIRED_SCOPES="mcp:thalovant"
123
+ ```
124
+
125
+ The server publishes protected resource metadata at:
126
+
127
+ ```text
128
+ https://mcp.example.com/.well-known/oauth-protected-resource
129
+ ```
130
+
131
+ 401 responses include `WWW-Authenticate` with a `resource_metadata` pointer for MCP clients that support OAuth discovery.
132
+
133
+ ## Principal Credentials
134
+
135
+ For multi-user remote deployments, do not share one Thalovant access token across all MCP users. Map each authenticated MCP principal to its own Thalovant control-plane token, runtime identity, and tool policy.
136
+
137
+ Single file:
138
+
139
+ ```bash
140
+ export THALOVANT_PRINCIPAL_CREDENTIALS_FILE="/run/secrets/thalovant-principals.json"
141
+ ```
142
+
143
+ Directory mode:
144
+
145
+ ```bash
146
+ export THALOVANT_PRINCIPAL_CREDENTIALS_DIR="/run/secrets/thalovant-principals"
147
+ ```
148
+
149
+ Directory files are named `<sha256(principal-id)>.json`. The server checks the OAuth subject, principal id, and client id. See [examples/principal-credentials.sample.json](examples/principal-credentials.sample.json).
150
+
151
+ Keep this disabled for multi-user deployments unless you intentionally want every remote principal to use the server environment's Thalovant credentials:
152
+
153
+ ```bash
154
+ export THALOVANT_ALLOW_SHARED_CREDENTIALS="false"
155
+ ```
156
+
157
+ Runtime `identityFile`, `configPath`, `profile`, and `fromEnv` tool arguments are disabled for remote principals by default. Set `MCP_HTTP_ALLOW_CLIENT_CREDENTIAL_PATHS=true` only for trusted private deployments.
158
+
159
+ ## Policy, Audit, And Resumability
160
+
161
+ Global tool policy:
162
+
163
+ ```bash
164
+ export MCP_TOOL_ALLOWLIST="thalovant_*"
165
+ export MCP_TOOL_DENYLIST="thalovant_delete_memory_item"
166
+ ```
167
+
168
+ Per-principal credential files may also include `allowedTools` and `deniedTools`.
169
+
170
+ Audit logs:
171
+
172
+ ```bash
173
+ export MCP_AUDIT_LOG="stderr" # off, stderr, file, or both
174
+ export MCP_AUDIT_LOG_FILE="/var/log/thalovant-mcp/audit.jsonl"
175
+ export MCP_AUDIT_INCLUDE_ARGS="false"
176
+ ```
177
+
178
+ Audit entries are JSONL and credential-shaped fields are redacted.
179
+
180
+ Streamable HTTP resumability defaults to an in-memory event store. Use a file-backed store for single-instance restarts:
181
+
182
+ ```bash
183
+ export MCP_EVENT_STORE_FILE="/var/lib/thalovant-mcp/events.jsonl"
184
+ ```
185
+
186
+ ## HTTP Hardening
187
+
188
+ - Bearer auth is required unless `MCP_HTTP_ALLOW_UNAUTHENTICATED=true` is explicitly set.
189
+ - Host headers are allowlisted to reduce DNS rebinding risk.
190
+ - Browser `Origin` headers are rejected unless they exactly match `MCP_HTTP_ALLOWED_ORIGINS`.
191
+ - CORS exposes only MCP session/protocol headers.
192
+ - Sessions use cryptographically random ids and are bound to the authenticated principal.
193
+ - Request bodies are capped by `MCP_HTTP_MAX_BODY_BYTES`, defaulting to 1 MiB.
194
+ - Fixed-window rate limiting defaults to 120 MCP requests per minute per client address.
195
+ - Security headers include `nosniff`, `DENY` framing, no referrer, and a restrictive CSP.
196
+
197
+ Useful HTTP environment variables:
198
+
199
+ ```bash
200
+ MCP_HTTP_PATH=/mcp
201
+ MCP_HTTP_RATE_LIMIT_MAX=120
202
+ MCP_HTTP_RATE_LIMIT_WINDOW_MS=60000
203
+ MCP_HTTP_SESSION_TTL_MS=3600000
204
+ MCP_HTTP_MAX_BODY_BYTES=1048576
205
+ MCP_HTTP_ENABLE_JSON_RESPONSE=false
206
+ MCP_HTTP_TRUST_PROXY=false
207
+ ```
208
+
209
+ ## Claude Desktop
210
+
211
+ ```json
212
+ {
213
+ "mcpServers": {
214
+ "thalovant": {
215
+ "command": "node",
216
+ "args": ["/home/goldyfruit/Development/Thalovant/mcp/dist/index.js"],
217
+ "env": {
218
+ "THALOVANT_PROFILE": "prod"
219
+ }
220
+ }
221
+ }
222
+ }
223
+ ```
224
+
225
+ ## Codex
226
+
227
+ Use the same stdio command in your MCP client config:
228
+
229
+ ```json
230
+ {
231
+ "mcpServers": {
232
+ "thalovant": {
233
+ "command": "node",
234
+ "args": ["/home/goldyfruit/Development/Thalovant/mcp/dist/index.js"],
235
+ "env": {
236
+ "THALOVANT_PROFILE": "prod"
237
+ }
238
+ }
239
+ }
240
+ }
241
+ ```
242
+
243
+ ## Tools
244
+
245
+ Read-only:
246
+
247
+ - `thalovant_config_status`
248
+ - `thalovant_list_public_hubs`
249
+ - `thalovant_get_public_hub`
250
+ - `thalovant_list_hubs`
251
+ - `thalovant_get_hub`
252
+ - `thalovant_identity_status`
253
+ - `thalovant_healthcheck`
254
+ - `thalovant_wait_for_event`
255
+ - `thalovant_get_analytics_overview`
256
+ - `thalovant_list_memory_items`
257
+ - `thalovant_get_memory_summary`
258
+ - `thalovant_get_memory_item`
259
+
260
+ Writes or hub events:
261
+
262
+ - `thalovant_create_client_identity`
263
+ - `thalovant_ask`
264
+ - `thalovant_send_action`
265
+ - `thalovant_send_code`
266
+ - `thalovant_emit_event`
267
+ - `thalovant_create_memory_item`
268
+ - `thalovant_update_memory_item`
269
+ - `thalovant_delete_memory_item`
270
+
271
+ Tool outputs redact credential-shaped fields. `thalovant_create_client_identity` does not return secret identity material; pass `savePath` when you want the full identity written to a local file with mode `0600`.
272
+
273
+ ## Development
274
+
275
+ ```bash
276
+ npm run typecheck
277
+ npm test
278
+ npm run build
279
+ npm run test:smoke
280
+ npm run test:http
281
+ npm run bench
282
+ npm run bench:http
283
+ npm pack --dry-run
284
+ ```
285
+
286
+ ## License
287
+
288
+ MIT. This is the right default for a public integration server: it is permissive, compatible with the MIT Thalovant Node SDK and MCP TypeScript SDK, and does not force downstream agent or enterprise users into a reciprocal licensing model.
package/SECURITY.md ADDED
@@ -0,0 +1,22 @@
1
+ # Security Policy
2
+
3
+ ## Supported Versions
4
+
5
+ Security fixes are applied to the current `0.x` line until a stable `1.0.0` release policy is published.
6
+
7
+ ## Reporting A Vulnerability
8
+
9
+ Do not open public issues for vulnerabilities. Email security reports to `hello@thalovant.com` with:
10
+
11
+ - affected version or commit
12
+ - reproduction steps
13
+ - impact
14
+ - suggested fix, if available
15
+
16
+ ## Operational Notes
17
+
18
+ - Use `MCP_HTTP_AUTH_MODE=jwt` or `MCP_HTTP_AUTH_MODE=introspection` for multi-user remote deployments.
19
+ - Use per-principal Thalovant credentials through `THALOVANT_PRINCIPAL_CREDENTIALS_FILE` or `THALOVANT_PRINCIPAL_CREDENTIALS_DIR`.
20
+ - Keep `THALOVANT_ALLOW_SHARED_CREDENTIALS=false` for multi-user deployments.
21
+ - Set exact `MCP_HTTP_ALLOWED_HOSTS` and `MCP_HTTP_ALLOWED_ORIGINS`.
22
+ - Send audit logs to your log pipeline with `MCP_AUDIT_LOG=stderr` or `MCP_AUDIT_LOG_FILE`.
@@ -0,0 +1,38 @@
1
+ #!/usr/bin/env node
2
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
3
+ interface HttpConfig {
4
+ host: string;
5
+ port: number;
6
+ path: string;
7
+ publicUrl: URL;
8
+ resourceUrl: URL;
9
+ resourceMetadataUrl: URL;
10
+ authTokens: string[];
11
+ allowUnauthenticated: boolean;
12
+ authMode: "static" | "jwt" | "introspection";
13
+ oauthIssuer?: string;
14
+ oauthJwksUrl?: string;
15
+ oauthAudience?: string;
16
+ oauthAuthorizationServers: string[];
17
+ oauthRequiredScopes: string[];
18
+ oauthScopesSupported: string[];
19
+ oauthIntrospectionUrl?: string;
20
+ oauthClientId?: string;
21
+ oauthClientSecret?: string;
22
+ allowedHosts: string[];
23
+ allowedOrigins: string[];
24
+ maxBodyBytes: number;
25
+ rateLimitMax: number;
26
+ rateLimitWindowMs: number;
27
+ sessionTtlMs: number;
28
+ eventStoreFile?: string;
29
+ enableJsonResponse: boolean;
30
+ trustProxy: boolean;
31
+ }
32
+ export declare function createServer(): McpServer;
33
+ export declare function startHttpServer(config?: HttpConfig): Promise<{
34
+ close: () => Promise<void>;
35
+ url: string;
36
+ }>;
37
+ export declare function main(): Promise<void>;
38
+ export {};