@clavisagent/mcp-server 0.1.1 → 0.1.2

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 CHANGED
@@ -1,91 +1,54 @@
1
- # @clavisagent/mcp-server
1
+ # Clavis MCP Server
2
2
 
3
- MCP server for [Clavis](https://clavisagent.com) — secure credential management for Claude Desktop.
3
+ Secure credential management for Claude Desktop and MCP servers.
4
4
 
5
- Credentials are injected server-side. **Claude never sees raw API keys.**
5
+ ## Features
6
+
7
+ - 🔐 Encrypted credential storage (AES-256)
8
+ - 🔄 Automatic OAuth token refresh
9
+ - ⚡ Distributed rate limiting
10
+ - 📊 Full audit logging
6
11
 
7
12
  ## Installation
8
13
 
14
+ ```bash
15
+ npx @clavisagent/mcp-server
16
+ ```
17
+
18
+ Or install globally:
19
+
9
20
  ```bash
10
21
  npm install -g @clavisagent/mcp-server
11
22
  ```
12
23
 
13
- ## Claude Desktop Setup
24
+ ## Usage with Claude Desktop
14
25
 
15
- Add to your `claude_desktop_config.json`:
26
+ Add the following to your Claude Desktop configuration file (`claude_desktop_config.json`):
16
27
 
17
28
  ```json
18
29
  {
19
30
  "mcpServers": {
20
31
  "clavis": {
21
32
  "command": "npx",
22
- "args": ["-y", "@clavisagent/mcp-server"],
23
- "env": {
24
- "CLAVIS_API_KEY": "eyJ...",
25
- "CLAVIS_API_URL": "https://your-clavis-instance.com"
26
- }
33
+ "args": ["-y", "@clavisagent/mcp-server"]
27
34
  }
28
35
  }
29
36
  }
30
37
  ```
31
38
 
32
- Config file locations:
33
- - **macOS:** `~/Library/Application Support/Claude/claude_desktop_config.json`
34
- - **Windows:** `%APPDATA%\Claude\claude_desktop_config.json`
35
-
36
- Get your API key from `POST /v1/auth/login` — use the `access_token` (JWT), not the `cla_...` key shown at registration.
37
-
38
- ## Tools
39
-
40
- ### `list_services`
41
- List all services with stored credentials.
42
-
43
- ### `check_credential_status`
44
- Check credential health without making any external API call.
45
- ```
46
- service_name: "stripe"
47
- → Valid: yes, Status: healthy, Expires in: 58 minutes
48
- ```
49
-
50
- ### `call_service` ← Recommended
51
- Make an API call with server-side credential injection. The credential never reaches Claude.
52
- ```
53
- service_name: "stripe"
54
- method: "GET"
55
- url: "https://api.stripe.com/v1/balance"
56
- → Status: 200, Body: {"object": "balance", ...}
57
- ```
58
-
59
- ### `get_credentials` ← Legacy
60
- Returns raw credential data. Use `call_service` instead — it keeps secrets out of the conversation entirely.
61
-
62
- ## Self-Hosted Setup
63
-
64
- If running Clavis locally:
39
+ ## Usage with Claude Code
65
40
 
66
- ```json
67
- {
68
- "mcpServers": {
69
- "clavis": {
70
- "command": "node",
71
- "args": ["/path/to/clavis-mcp/dist/index.js"],
72
- "env": {
73
- "CLAVIS_API_KEY": "eyJ...",
74
- "CLAVIS_API_URL": "http://localhost:8000"
75
- }
76
- }
77
- }
78
- }
41
+ ```bash
42
+ claude mcp add clavis -- npx -y @clavisagent/mcp-server
79
43
  ```
80
44
 
81
- ## Changelog
82
-
83
- ### v0.1.1
84
- - Added `call_service` tool (server-side credential injection)
85
- - `call_service` is the recommended tool for prompt injection immunity
45
+ ## Available Tools
86
46
 
87
- ### v0.1.0
88
- - Initial release: `list_services`, `check_credential_status`, `get_credentials`
47
+ | Tool | Description |
48
+ |---|---|
49
+ | `get_credentials` | Retrieve a valid access token or API key for a named service |
50
+ | `list_services` | List all services with stored credentials |
51
+ | `check_credential_status` | Check the status and expiry of credentials for a service |
89
52
 
90
53
  ## License
91
54
 
package/dist/index.d.ts CHANGED
@@ -2,9 +2,9 @@
2
2
  /**
3
3
  * Clavis MCP Server
4
4
  *
5
- * Exposes Clavis credential management to Claude Desktop via the
6
- * Model Context Protocol. Credentials are injected server-side —
7
- * Claude never sees raw API keys.
5
+ * Exposes Clavis credential management to Claude Desktop and other MCP clients.
6
+ * Configure via environment variable:
7
+ * CLAVIS_API_KEY your Clavis JWT (from POST /v1/auth/login)
8
8
  */
9
9
  export {};
10
10
  //# sourceMappingURL=index.d.ts.map
package/dist/index.js CHANGED
@@ -1,274 +1,138 @@
1
1
  #!/usr/bin/env node
2
- "use strict";
3
2
  /**
4
3
  * Clavis MCP Server
5
4
  *
6
- * Exposes Clavis credential management to Claude Desktop via the
7
- * Model Context Protocol. Credentials are injected server-side —
8
- * Claude never sees raw API keys.
5
+ * Exposes Clavis credential management to Claude Desktop and other MCP clients.
6
+ * Configure via environment variable:
7
+ * CLAVIS_API_KEY your Clavis JWT (from POST /v1/auth/login)
9
8
  */
10
- Object.defineProperty(exports, "__esModule", { value: true });
11
- const index_js_1 = require("@modelcontextprotocol/sdk/server/index.js");
12
- const stdio_js_1 = require("@modelcontextprotocol/sdk/server/stdio.js");
13
- const types_js_1 = require("@modelcontextprotocol/sdk/types.js");
9
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
10
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
11
+ import { z } from "zod";
14
12
  // ---------------------------------------------------------------------------
15
- // Config from environment
13
+ // Config
16
14
  // ---------------------------------------------------------------------------
17
- const CLAVIS_API_URL = (process.env.CLAVIS_API_URL ?? "http://localhost:8000").replace(/\/$/, "");
18
- const CLAVIS_API_KEY = process.env.CLAVIS_API_KEY ?? "";
19
- if (!CLAVIS_API_KEY) {
20
- process.stderr.write("[clavis-mcp] WARNING: CLAVIS_API_KEY is not set. All requests will fail with 401.\n");
15
+ const BASE_URL = "https://clavisagent.com";
16
+ const apiKey = process.env.CLAVIS_API_KEY;
17
+ if (!apiKey) {
18
+ console.error("[clavis-mcp] Error: CLAVIS_API_KEY environment variable is not set.");
19
+ process.exit(1);
21
20
  }
22
- const AUTH_HEADERS = {
23
- Authorization: `Bearer ${CLAVIS_API_KEY}`,
21
+ const authHeaders = {
22
+ Authorization: `Bearer ${apiKey}`,
24
23
  "Content-Type": "application/json",
25
24
  };
26
- // ---------------------------------------------------------------------------
27
- // Clavis API helpers
28
- // ---------------------------------------------------------------------------
29
25
  async function clavisGet(path) {
30
- const { default: fetch } = await import("node-fetch");
31
- const url = `${CLAVIS_API_URL}${path}`;
32
- const res = await fetch(url, { headers: AUTH_HEADERS });
33
- const body = await res.json();
26
+ const url = `${BASE_URL}${path}`;
27
+ const res = await fetch(url, { headers: authHeaders });
34
28
  if (!res.ok) {
35
- const detail = body.detail ?? res.statusText;
36
- throw new Error(`Clavis API error ${res.status}: ${detail}`);
37
- }
38
- return body;
39
- }
40
- async function clavisPost(path, payload) {
41
- const { default: fetch } = await import("node-fetch");
42
- const url = `${CLAVIS_API_URL}${path}`;
43
- const res = await fetch(url, {
44
- method: "POST",
45
- headers: AUTH_HEADERS,
46
- body: JSON.stringify(payload),
47
- });
48
- const body = await res.json();
49
- if (!res.ok) {
50
- const detail = body.detail ?? res.statusText;
51
- throw new Error(`Clavis API error ${res.status}: ${detail}`);
29
+ let detail = `HTTP ${res.status}`;
30
+ try {
31
+ const body = (await res.json());
32
+ detail = body.detail ?? body.message ?? detail;
33
+ }
34
+ catch {
35
+ // ignore parse error use status code only
36
+ }
37
+ throw new Error(`Clavis API error on ${path}: ${detail}`);
52
38
  }
53
- return body;
39
+ return res.json();
54
40
  }
55
41
  // ---------------------------------------------------------------------------
56
- // Tool definitions
42
+ // MCP Server
57
43
  // ---------------------------------------------------------------------------
58
- const TOOLS = [
59
- {
60
- name: "list_services",
61
- description: "List all services with stored credentials in Clavis. Returns service names and connector types.",
62
- inputSchema: {
63
- type: "object",
64
- properties: {},
65
- required: [],
66
- },
67
- },
68
- {
69
- name: "check_credential_status",
70
- description: "Check credential health for a service without making any external API call. " +
71
- "Returns validity, expiry, and rate-limit info. Safe to call frequently as a health check.",
72
- inputSchema: {
73
- type: "object",
74
- properties: {
75
- service_name: {
76
- type: "string",
77
- description: "Name of the service to check (e.g. 'openai', 'stripe')",
78
- },
79
- },
80
- required: ["service_name"],
81
- },
82
- },
83
- {
84
- name: "call_service",
85
- description: "RECOMMENDED: Make an API call with server-side credential injection. " +
86
- "The credential is fetched from the Clavis vault and injected into the upstream request. " +
87
- "Claude never sees the raw API key — this is the secure way to call external APIs.",
88
- inputSchema: {
89
- type: "object",
90
- properties: {
91
- service_name: {
92
- type: "string",
93
- description: "Name of the Clavis service whose credentials to inject (e.g. 'openai')",
94
- },
95
- method: {
96
- type: "string",
97
- enum: ["GET", "POST", "PUT", "PATCH", "DELETE"],
98
- description: "HTTP method",
99
- },
100
- url: {
101
- type: "string",
102
- description: "Full URL to call. Must be on the service's allowed domain (SSRF protection).",
103
- },
104
- headers: {
105
- type: "object",
106
- description: "Additional request headers (optional)",
107
- additionalProperties: { type: "string" },
108
- },
109
- params: {
110
- type: "object",
111
- description: "URL query parameters (optional)",
112
- additionalProperties: true,
113
- },
114
- json: {
115
- type: "object",
116
- description: "JSON request body (optional, mutually exclusive with data)",
117
- additionalProperties: true,
118
- },
119
- data: {
120
- description: "Form-encoded body (optional, mutually exclusive with json)",
121
- },
122
- },
123
- required: ["service_name", "method", "url"],
124
- },
125
- },
126
- {
127
- name: "get_credentials",
128
- description: "LEGACY — returns raw credential data. Prefer call_service for security: " +
129
- "call_service injects credentials server-side so Claude never sees raw keys. " +
130
- "Use this only if you need the credential value directly.",
131
- inputSchema: {
132
- type: "object",
133
- properties: {
134
- service_name: {
135
- type: "string",
136
- description: "Name of the service (e.g. 'openai', 'stripe')",
137
- },
44
+ const server = new McpServer({
45
+ name: "clavis",
46
+ version: "0.1.0",
47
+ });
48
+ // ── Tool 1: get_credentials ────────────────────────────────────────────────
49
+ server.tool("get_credentials", "Retrieve a valid access token or API key for a named service from Clavis. " +
50
+ "Clavis handles token refresh and rotation automatically.", {
51
+ service_name: z
52
+ .string()
53
+ .min(1)
54
+ .describe("The name of the service to retrieve credentials for (e.g. 'github', 'openai')"),
55
+ }, async ({ service_name }) => {
56
+ const data = await clavisGet(`/v1/tokens/${service_name}`);
57
+ return {
58
+ content: [
59
+ {
60
+ type: "text",
61
+ text: JSON.stringify({
62
+ service: service_name,
63
+ access_token: data.access_token,
64
+ token_type: data.token_type ?? "Bearer",
65
+ ...(data.expires_in != null && { expires_in_seconds: data.expires_in }),
66
+ }, null, 2),
138
67
  },
139
- required: ["service_name"],
140
- },
141
- },
142
- ];
143
- // ---------------------------------------------------------------------------
144
- // Tool handlers
145
- // ---------------------------------------------------------------------------
146
- async function handleListServices() {
68
+ ],
69
+ };
70
+ });
71
+ // ── Tool 2: list_services ─────────────────────────────────────────────────
72
+ server.tool("list_services", "List all services configured in Clavis for the authenticated developer.", {}, async () => {
147
73
  const data = await clavisGet("/v1/services");
148
- const items = Array.isArray(data)
74
+ // Normalise: API may return an array directly or wrapped in { services: [...] }
75
+ const services = Array.isArray(data)
149
76
  ? data
150
- : data.items
151
- ?? data.services
152
- ?? [];
153
- if (items.length === 0) {
154
- return "No services registered in Clavis yet. Add one via the Clavis API or dashboard.";
155
- }
156
- const lines = items.map((s) => {
157
- const svc = s;
158
- const name = svc.name ?? svc.service_name ?? "unknown";
159
- const connector = svc.connector_name ? ` (${svc.connector_name})` : "";
160
- return `- ${name}${connector}`;
161
- });
162
- return `${items.length} service(s) registered:\n${lines.join("\n")}`;
163
- }
164
- async function handleCheckCredentialStatus(serviceName) {
165
- const data = await clavisGet(`/v1/credentials/${encodeURIComponent(serviceName)}/check`);
166
- const lines = [
167
- `Service: ${serviceName}`,
168
- `Valid: ${data.valid ? "yes" : "no"}`,
169
- `Status: ${data.status ?? "unknown"}`,
170
- ];
171
- if (data.expires_in != null) {
172
- const mins = Math.floor(data.expires_in / 60);
173
- lines.push(`Expires in: ${mins > 0 ? `${mins} minutes` : "< 1 minute"}`);
174
- }
175
- if (data.rate_limit_remaining != null) {
176
- lines.push(`Rate limit remaining: ${data.rate_limit_remaining}`);
177
- }
178
- if (data.last_used) {
179
- lines.push(`Last used: ${data.last_used}`);
180
- }
181
- if (!data.valid && data.error) {
182
- lines.push(`Error: ${data.error}`);
183
- }
184
- return lines.join("\n");
185
- }
186
- async function handleCallService(args) {
187
- const payload = {
188
- method: args.method,
189
- url: args.url,
190
- headers: args.headers ?? null,
191
- params: args.params ?? null,
192
- json: args.json ?? null,
193
- data: args.data ?? null,
77
+ : data.services ?? [];
78
+ const active = services.filter((s) => s.is_active);
79
+ return {
80
+ content: [
81
+ {
82
+ type: "text",
83
+ text: JSON.stringify({
84
+ total: services.length,
85
+ active: active.length,
86
+ services: services.map((s) => ({
87
+ name: s.name,
88
+ id: s.id,
89
+ is_active: s.is_active,
90
+ created_at: s.created_at,
91
+ })),
92
+ }, null, 2),
93
+ },
94
+ ],
95
+ };
96
+ });
97
+ // ── Tool 3: check_credential_status ───────────────────────────────────────
98
+ server.tool("check_credential_status", "Check the validity and rate-limit status of credentials for a service. " +
99
+ "NOTE: The /v1/credentials/{service}/check endpoint is not yet implemented — " +
100
+ "returns a stub response until the API endpoint is live.", {
101
+ service_name: z
102
+ .string()
103
+ .min(1)
104
+ .describe("The name of the service to check (e.g. 'github', 'openai')"),
105
+ }, async ({ service_name }) => {
106
+ // Stub — endpoint /v1/credentials/{service_name}/check is not yet implemented.
107
+ // When the endpoint goes live, replace the body below with:
108
+ // const data = await clavisGet<CredentialStatus>(`/v1/credentials/${service_name}/check`);
109
+ // return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
110
+ const stub = {
111
+ service_name,
112
+ valid: true,
113
+ expires_in: undefined,
114
+ rate_limit_remaining: undefined,
115
+ note: "check_credential_status is stubbed — /v1/credentials/{service}/check not yet implemented.",
116
+ };
117
+ return {
118
+ content: [
119
+ {
120
+ type: "text",
121
+ text: JSON.stringify(stub, null, 2),
122
+ },
123
+ ],
194
124
  };
195
- const result = await clavisPost(`/v1/call/${encodeURIComponent(args.service_name)}`, payload);
196
- const bodyStr = typeof result.body === "string"
197
- ? result.body
198
- : JSON.stringify(result.body, null, 2);
199
- return [`Status: ${result.status_code}`, `Body:\n${bodyStr}`].join("\n");
200
- }
201
- async function handleGetCredentials(serviceName) {
202
- const data = await clavisGet(`/v1/credentials/${encodeURIComponent(serviceName)}`);
203
- return ("WARNING: This returned raw credential data. " +
204
- "For future calls, prefer call_service — it injects credentials server-side " +
205
- "so this conversation never contains raw API keys.\n\n" +
206
- JSON.stringify(data, null, 2));
207
- }
208
- // ---------------------------------------------------------------------------
209
- // MCP Server
210
- // ---------------------------------------------------------------------------
211
- const server = new index_js_1.Server({ name: "clavis", version: "0.1.1" }, { capabilities: { tools: {} } });
212
- server.setRequestHandler(types_js_1.ListToolsRequestSchema, async () => ({ tools: TOOLS }));
213
- server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
214
- const { name, arguments: args } = request.params;
215
- const a = (args ?? {});
216
- try {
217
- let text;
218
- switch (name) {
219
- case "list_services":
220
- text = await handleListServices();
221
- break;
222
- case "check_credential_status":
223
- if (typeof a.service_name !== "string")
224
- throw new Error("service_name is required");
225
- text = await handleCheckCredentialStatus(a.service_name);
226
- break;
227
- case "call_service":
228
- if (typeof a.service_name !== "string")
229
- throw new Error("service_name is required");
230
- if (typeof a.method !== "string")
231
- throw new Error("method is required");
232
- if (typeof a.url !== "string")
233
- throw new Error("url is required");
234
- text = await handleCallService({
235
- service_name: a.service_name,
236
- method: a.method,
237
- url: a.url,
238
- headers: a.headers,
239
- params: a.params,
240
- json: a.json,
241
- data: a.data,
242
- });
243
- break;
244
- case "get_credentials":
245
- if (typeof a.service_name !== "string")
246
- throw new Error("service_name is required");
247
- text = await handleGetCredentials(a.service_name);
248
- break;
249
- default:
250
- throw new Error(`Unknown tool: ${name}`);
251
- }
252
- return { content: [{ type: "text", text }] };
253
- }
254
- catch (err) {
255
- const message = err instanceof Error ? err.message : String(err);
256
- return {
257
- content: [{ type: "text", text: `Error: ${message}` }],
258
- isError: true,
259
- };
260
- }
261
125
  });
262
126
  // ---------------------------------------------------------------------------
263
127
  // Start
264
128
  // ---------------------------------------------------------------------------
265
129
  async function main() {
266
- const transport = new stdio_js_1.StdioServerTransport();
130
+ const transport = new StdioServerTransport();
267
131
  await server.connect(transport);
268
- process.stderr.write(`[clavis-mcp] Server started. API: ${CLAVIS_API_URL}\n`);
132
+ console.error("[clavis-mcp] Server running on stdio");
269
133
  }
270
134
  main().catch((err) => {
271
- process.stderr.write(`[clavis-mcp] Fatal: ${err}\n`);
135
+ console.error("[clavis-mcp] Fatal error:", err);
272
136
  process.exit(1);
273
137
  });
274
138
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,32 +1,53 @@
1
1
  {
2
2
  "name": "@clavisagent/mcp-server",
3
- "version": "0.1.1",
4
- "description": "MCP server for Clavis — secure credential management for Claude Desktop",
5
- "main": "dist/index.js",
3
+ "version": "0.1.2",
4
+ "mcpName": "io.github.KN0WBOT/clavis",
5
+ "description": "MCP server for secure credential management. Handles encrypted storage, auto token refresh, and rate limiting for Claude Desktop and AI agents.",
6
+ "type": "module",
7
+ "author": "Clavis",
8
+ "license": "MIT",
9
+ "homepage": "https://clavisagent.com",
10
+ "repository": {
11
+ "type": "git",
12
+ "url": "https://github.com/KN0WBOT/clavis-mcp.git"
13
+ },
14
+ "keywords": [
15
+ "mcp",
16
+ "model-context-protocol",
17
+ "claude",
18
+ "anthropic",
19
+ "credentials",
20
+ "authentication",
21
+ "api-keys",
22
+ "oauth",
23
+ "token-refresh",
24
+ "rate-limiting",
25
+ "ai-agents",
26
+ "security"
27
+ ],
6
28
  "bin": {
7
- "clavis-mcp": "dist/index.js"
29
+ "clavis-mcp": "./dist/index.js"
8
30
  },
31
+ "main": "./dist/index.js",
32
+ "files": [
33
+ "dist/",
34
+ "README.md",
35
+ "LICENSE"
36
+ ],
9
37
  "scripts": {
10
38
  "build": "tsc",
11
- "start": "node dist/index.js",
12
- "dev": "ts-node src/index.ts"
39
+ "dev": "tsc --watch",
40
+ "start": "node dist/index.js"
13
41
  },
14
42
  "dependencies": {
15
- "@modelcontextprotocol/sdk": "^1.0.0",
16
- "node-fetch": "^3.3.2"
43
+ "@modelcontextprotocol/sdk": "^1.9.0",
44
+ "zod": "^3.23.8"
17
45
  },
18
46
  "devDependencies": {
19
- "@types/node": "^20.0.0",
20
- "typescript": "^5.4.0",
21
- "ts-node": "^10.9.0"
47
+ "@types/node": "^22.0.0",
48
+ "typescript": "^5.5.0"
22
49
  },
23
50
  "engines": {
24
51
  "node": ">=18"
25
- },
26
- "license": "MIT",
27
- "repository": {
28
- "type": "git",
29
- "url": "https://github.com/KN0WBOT/clavis"
30
- },
31
- "keywords": ["mcp", "clavis", "credentials", "claude", "ai-agents"]
52
+ }
32
53
  }
package/src/index.ts DELETED
@@ -1,342 +0,0 @@
1
- #!/usr/bin/env node
2
- /**
3
- * Clavis MCP Server
4
- *
5
- * Exposes Clavis credential management to Claude Desktop via the
6
- * Model Context Protocol. Credentials are injected server-side —
7
- * Claude never sees raw API keys.
8
- */
9
-
10
- import { Server } from "@modelcontextprotocol/sdk/server/index.js";
11
- import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
12
- import {
13
- CallToolRequestSchema,
14
- ListToolsRequestSchema,
15
- Tool,
16
- } from "@modelcontextprotocol/sdk/types.js";
17
-
18
- // ---------------------------------------------------------------------------
19
- // Config from environment
20
- // ---------------------------------------------------------------------------
21
-
22
- const CLAVIS_API_URL = (process.env.CLAVIS_API_URL ?? "http://localhost:8000").replace(/\/$/, "");
23
- const CLAVIS_API_KEY = process.env.CLAVIS_API_KEY ?? "";
24
-
25
- if (!CLAVIS_API_KEY) {
26
- process.stderr.write(
27
- "[clavis-mcp] WARNING: CLAVIS_API_KEY is not set. All requests will fail with 401.\n"
28
- );
29
- }
30
-
31
- const AUTH_HEADERS: Record<string, string> = {
32
- Authorization: `Bearer ${CLAVIS_API_KEY}`,
33
- "Content-Type": "application/json",
34
- };
35
-
36
- // ---------------------------------------------------------------------------
37
- // Clavis API helpers
38
- // ---------------------------------------------------------------------------
39
-
40
- async function clavisGet(path: string): Promise<unknown> {
41
- const { default: fetch } = await import("node-fetch");
42
- const url = `${CLAVIS_API_URL}${path}`;
43
- const res = await fetch(url, { headers: AUTH_HEADERS });
44
- const body = await res.json() as unknown;
45
- if (!res.ok) {
46
- const detail = (body as { detail?: string }).detail ?? res.statusText;
47
- throw new Error(`Clavis API error ${res.status}: ${detail}`);
48
- }
49
- return body;
50
- }
51
-
52
- async function clavisPost(path: string, payload: unknown): Promise<unknown> {
53
- const { default: fetch } = await import("node-fetch");
54
- const url = `${CLAVIS_API_URL}${path}`;
55
- const res = await fetch(url, {
56
- method: "POST",
57
- headers: AUTH_HEADERS,
58
- body: JSON.stringify(payload),
59
- });
60
- const body = await res.json() as unknown;
61
- if (!res.ok) {
62
- const detail = (body as { detail?: string }).detail ?? res.statusText;
63
- throw new Error(`Clavis API error ${res.status}: ${detail}`);
64
- }
65
- return body;
66
- }
67
-
68
- // ---------------------------------------------------------------------------
69
- // Tool definitions
70
- // ---------------------------------------------------------------------------
71
-
72
- const TOOLS: Tool[] = [
73
- {
74
- name: "list_services",
75
- description:
76
- "List all services with stored credentials in Clavis. Returns service names and connector types.",
77
- inputSchema: {
78
- type: "object",
79
- properties: {},
80
- required: [],
81
- },
82
- },
83
- {
84
- name: "check_credential_status",
85
- description:
86
- "Check credential health for a service without making any external API call. " +
87
- "Returns validity, expiry, and rate-limit info. Safe to call frequently as a health check.",
88
- inputSchema: {
89
- type: "object",
90
- properties: {
91
- service_name: {
92
- type: "string",
93
- description: "Name of the service to check (e.g. 'openai', 'stripe')",
94
- },
95
- },
96
- required: ["service_name"],
97
- },
98
- },
99
- {
100
- name: "call_service",
101
- description:
102
- "RECOMMENDED: Make an API call with server-side credential injection. " +
103
- "The credential is fetched from the Clavis vault and injected into the upstream request. " +
104
- "Claude never sees the raw API key — this is the secure way to call external APIs.",
105
- inputSchema: {
106
- type: "object",
107
- properties: {
108
- service_name: {
109
- type: "string",
110
- description: "Name of the Clavis service whose credentials to inject (e.g. 'openai')",
111
- },
112
- method: {
113
- type: "string",
114
- enum: ["GET", "POST", "PUT", "PATCH", "DELETE"],
115
- description: "HTTP method",
116
- },
117
- url: {
118
- type: "string",
119
- description:
120
- "Full URL to call. Must be on the service's allowed domain (SSRF protection).",
121
- },
122
- headers: {
123
- type: "object",
124
- description: "Additional request headers (optional)",
125
- additionalProperties: { type: "string" },
126
- },
127
- params: {
128
- type: "object",
129
- description: "URL query parameters (optional)",
130
- additionalProperties: true,
131
- },
132
- json: {
133
- type: "object",
134
- description: "JSON request body (optional, mutually exclusive with data)",
135
- additionalProperties: true,
136
- },
137
- data: {
138
- description: "Form-encoded body (optional, mutually exclusive with json)",
139
- },
140
- },
141
- required: ["service_name", "method", "url"],
142
- },
143
- },
144
- {
145
- name: "get_credentials",
146
- description:
147
- "LEGACY — returns raw credential data. Prefer call_service for security: " +
148
- "call_service injects credentials server-side so Claude never sees raw keys. " +
149
- "Use this only if you need the credential value directly.",
150
- inputSchema: {
151
- type: "object",
152
- properties: {
153
- service_name: {
154
- type: "string",
155
- description: "Name of the service (e.g. 'openai', 'stripe')",
156
- },
157
- },
158
- required: ["service_name"],
159
- },
160
- },
161
- ];
162
-
163
- // ---------------------------------------------------------------------------
164
- // Tool handlers
165
- // ---------------------------------------------------------------------------
166
-
167
- async function handleListServices(): Promise<string> {
168
- const data = await clavisGet("/v1/services") as { items?: unknown[]; services?: unknown[] } | unknown[];
169
- const items: unknown[] = Array.isArray(data)
170
- ? data
171
- : (data as { items?: unknown[]; services?: unknown[] }).items
172
- ?? (data as { services?: unknown[] }).services
173
- ?? [];
174
-
175
- if (items.length === 0) {
176
- return "No services registered in Clavis yet. Add one via the Clavis API or dashboard.";
177
- }
178
-
179
- const lines = items.map((s) => {
180
- const svc = s as { name?: string; service_name?: string; connector_name?: string };
181
- const name = svc.name ?? svc.service_name ?? "unknown";
182
- const connector = svc.connector_name ? ` (${svc.connector_name})` : "";
183
- return `- ${name}${connector}`;
184
- });
185
-
186
- return `${items.length} service(s) registered:\n${lines.join("\n")}`;
187
- }
188
-
189
- async function handleCheckCredentialStatus(serviceName: string): Promise<string> {
190
- const data = await clavisGet(`/v1/credentials/${encodeURIComponent(serviceName)}/check`) as {
191
- valid?: boolean;
192
- status?: string;
193
- expires_in?: number | null;
194
- rate_limit_remaining?: number | null;
195
- last_used?: string | null;
196
- error?: string;
197
- };
198
-
199
- const lines: string[] = [
200
- `Service: ${serviceName}`,
201
- `Valid: ${data.valid ? "yes" : "no"}`,
202
- `Status: ${data.status ?? "unknown"}`,
203
- ];
204
-
205
- if (data.expires_in != null) {
206
- const mins = Math.floor(data.expires_in / 60);
207
- lines.push(`Expires in: ${mins > 0 ? `${mins} minutes` : "< 1 minute"}`);
208
- }
209
- if (data.rate_limit_remaining != null) {
210
- lines.push(`Rate limit remaining: ${data.rate_limit_remaining}`);
211
- }
212
- if (data.last_used) {
213
- lines.push(`Last used: ${data.last_used}`);
214
- }
215
- if (!data.valid && data.error) {
216
- lines.push(`Error: ${data.error}`);
217
- }
218
-
219
- return lines.join("\n");
220
- }
221
-
222
- async function handleCallService(args: {
223
- service_name: string;
224
- method: string;
225
- url: string;
226
- headers?: Record<string, string>;
227
- params?: Record<string, unknown>;
228
- json?: Record<string, unknown>;
229
- data?: unknown;
230
- }): Promise<string> {
231
- const payload = {
232
- method: args.method,
233
- url: args.url,
234
- headers: args.headers ?? null,
235
- params: args.params ?? null,
236
- json: args.json ?? null,
237
- data: args.data ?? null,
238
- };
239
-
240
- const result = await clavisPost(
241
- `/v1/call/${encodeURIComponent(args.service_name)}`,
242
- payload
243
- ) as {
244
- status_code: number;
245
- headers: Record<string, string>;
246
- body: unknown;
247
- };
248
-
249
- const bodyStr =
250
- typeof result.body === "string"
251
- ? result.body
252
- : JSON.stringify(result.body, null, 2);
253
-
254
- return [`Status: ${result.status_code}`, `Body:\n${bodyStr}`].join("\n");
255
- }
256
-
257
- async function handleGetCredentials(serviceName: string): Promise<string> {
258
- const data = await clavisGet(`/v1/credentials/${encodeURIComponent(serviceName)}`);
259
- return (
260
- "WARNING: This returned raw credential data. " +
261
- "For future calls, prefer call_service — it injects credentials server-side " +
262
- "so this conversation never contains raw API keys.\n\n" +
263
- JSON.stringify(data, null, 2)
264
- );
265
- }
266
-
267
- // ---------------------------------------------------------------------------
268
- // MCP Server
269
- // ---------------------------------------------------------------------------
270
-
271
- const server = new Server(
272
- { name: "clavis", version: "0.1.1" },
273
- { capabilities: { tools: {} } }
274
- );
275
-
276
- server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools: TOOLS }));
277
-
278
- server.setRequestHandler(CallToolRequestSchema, async (request) => {
279
- const { name, arguments: args } = request.params;
280
- const a = (args ?? {}) as Record<string, unknown>;
281
-
282
- try {
283
- let text: string;
284
-
285
- switch (name) {
286
- case "list_services":
287
- text = await handleListServices();
288
- break;
289
-
290
- case "check_credential_status":
291
- if (typeof a.service_name !== "string") throw new Error("service_name is required");
292
- text = await handleCheckCredentialStatus(a.service_name);
293
- break;
294
-
295
- case "call_service":
296
- if (typeof a.service_name !== "string") throw new Error("service_name is required");
297
- if (typeof a.method !== "string") throw new Error("method is required");
298
- if (typeof a.url !== "string") throw new Error("url is required");
299
- text = await handleCallService({
300
- service_name: a.service_name,
301
- method: a.method,
302
- url: a.url,
303
- headers: a.headers as Record<string, string> | undefined,
304
- params: a.params as Record<string, unknown> | undefined,
305
- json: a.json as Record<string, unknown> | undefined,
306
- data: a.data,
307
- });
308
- break;
309
-
310
- case "get_credentials":
311
- if (typeof a.service_name !== "string") throw new Error("service_name is required");
312
- text = await handleGetCredentials(a.service_name);
313
- break;
314
-
315
- default:
316
- throw new Error(`Unknown tool: ${name}`);
317
- }
318
-
319
- return { content: [{ type: "text", text }] };
320
- } catch (err) {
321
- const message = err instanceof Error ? err.message : String(err);
322
- return {
323
- content: [{ type: "text", text: `Error: ${message}` }],
324
- isError: true,
325
- };
326
- }
327
- });
328
-
329
- // ---------------------------------------------------------------------------
330
- // Start
331
- // ---------------------------------------------------------------------------
332
-
333
- async function main(): Promise<void> {
334
- const transport = new StdioServerTransport();
335
- await server.connect(transport);
336
- process.stderr.write(`[clavis-mcp] Server started. API: ${CLAVIS_API_URL}\n`);
337
- }
338
-
339
- main().catch((err) => {
340
- process.stderr.write(`[clavis-mcp] Fatal: ${err}\n`);
341
- process.exit(1);
342
- });
package/tsconfig.json DELETED
@@ -1,17 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "target": "ES2022",
4
- "module": "Node16",
5
- "moduleResolution": "Node16",
6
- "outDir": "./dist",
7
- "rootDir": "./src",
8
- "strict": true,
9
- "esModuleInterop": true,
10
- "skipLibCheck": true,
11
- "declaration": true,
12
- "declarationMap": true,
13
- "sourceMap": true
14
- },
15
- "include": ["src/**/*"],
16
- "exclude": ["node_modules", "dist"]
17
- }