@clavisagent/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/README.md +55 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +138 -0
- package/dist/index.js.map +1 -0
- package/package.json +48 -0
package/README.md
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# Clavis MCP Server
|
|
2
|
+
|
|
3
|
+
Secure credential management for Claude Desktop and MCP servers.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- 🔐 Encrypted credential storage (AES-256)
|
|
8
|
+
- 🔄 Automatic OAuth token refresh
|
|
9
|
+
- ⚡ Distributed rate limiting
|
|
10
|
+
- 📊 Full audit logging
|
|
11
|
+
|
|
12
|
+
## Installation
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
npx @clavisagent/mcp-server
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
Or install globally:
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
npm install -g @clavisagent/mcp-server
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Usage with Claude Desktop
|
|
25
|
+
|
|
26
|
+
Add the following to your Claude Desktop configuration file (`claude_desktop_config.json`):
|
|
27
|
+
|
|
28
|
+
```json
|
|
29
|
+
{
|
|
30
|
+
"mcpServers": {
|
|
31
|
+
"clavis": {
|
|
32
|
+
"command": "npx",
|
|
33
|
+
"args": ["-y", "@clavisagent/mcp-server"]
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Usage with Claude Code
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
claude mcp add clavis -- npx -y @clavisagent/mcp-server
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Available Tools
|
|
46
|
+
|
|
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 |
|
|
52
|
+
|
|
53
|
+
## License
|
|
54
|
+
|
|
55
|
+
MIT
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Clavis MCP Server
|
|
4
|
+
*
|
|
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
|
+
*/
|
|
9
|
+
export {};
|
|
10
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;;;;GAMG"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Clavis MCP Server
|
|
4
|
+
*
|
|
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
|
+
*/
|
|
9
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
10
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
11
|
+
import { z } from "zod";
|
|
12
|
+
// ---------------------------------------------------------------------------
|
|
13
|
+
// Config
|
|
14
|
+
// ---------------------------------------------------------------------------
|
|
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);
|
|
20
|
+
}
|
|
21
|
+
const authHeaders = {
|
|
22
|
+
Authorization: `Bearer ${apiKey}`,
|
|
23
|
+
"Content-Type": "application/json",
|
|
24
|
+
};
|
|
25
|
+
async function clavisGet(path) {
|
|
26
|
+
const url = `${BASE_URL}${path}`;
|
|
27
|
+
const res = await fetch(url, { headers: authHeaders });
|
|
28
|
+
if (!res.ok) {
|
|
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}`);
|
|
38
|
+
}
|
|
39
|
+
return res.json();
|
|
40
|
+
}
|
|
41
|
+
// ---------------------------------------------------------------------------
|
|
42
|
+
// MCP Server
|
|
43
|
+
// ---------------------------------------------------------------------------
|
|
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),
|
|
67
|
+
},
|
|
68
|
+
],
|
|
69
|
+
};
|
|
70
|
+
});
|
|
71
|
+
// ── Tool 2: list_services ─────────────────────────────────────────────────
|
|
72
|
+
server.tool("list_services", "List all services configured in Clavis for the authenticated developer.", {}, async () => {
|
|
73
|
+
const data = await clavisGet("/v1/services");
|
|
74
|
+
// Normalise: API may return an array directly or wrapped in { services: [...] }
|
|
75
|
+
const services = Array.isArray(data)
|
|
76
|
+
? data
|
|
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
|
+
],
|
|
124
|
+
};
|
|
125
|
+
});
|
|
126
|
+
// ---------------------------------------------------------------------------
|
|
127
|
+
// Start
|
|
128
|
+
// ---------------------------------------------------------------------------
|
|
129
|
+
async function main() {
|
|
130
|
+
const transport = new StdioServerTransport();
|
|
131
|
+
await server.connect(transport);
|
|
132
|
+
console.error("[clavis-mcp] Server running on stdio");
|
|
133
|
+
}
|
|
134
|
+
main().catch((err) => {
|
|
135
|
+
console.error("[clavis-mcp] Fatal error:", err);
|
|
136
|
+
process.exit(1);
|
|
137
|
+
});
|
|
138
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;;;;GAMG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,8EAA8E;AAC9E,SAAS;AACT,8EAA8E;AAE9E,MAAM,QAAQ,GAAG,yBAAyB,CAAC;AAE3C,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC;AAC1C,IAAI,CAAC,MAAM,EAAE,CAAC;IACZ,OAAO,CAAC,KAAK,CAAC,qEAAqE,CAAC,CAAC;IACrF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,MAAM,WAAW,GAA2B;IAC1C,aAAa,EAAE,UAAU,MAAM,EAAE;IACjC,cAAc,EAAE,kBAAkB;CACnC,CAAC;AAWF,KAAK,UAAU,SAAS,CAAI,IAAY;IACtC,MAAM,GAAG,GAAG,GAAG,QAAQ,GAAG,IAAI,EAAE,CAAC;IACjC,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC,CAAC;IAEvD,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,IAAI,MAAM,GAAG,QAAQ,GAAG,CAAC,MAAM,EAAE,CAAC;QAClC,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAgB,CAAC;YAC/C,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,OAAO,IAAI,MAAM,CAAC;QACjD,CAAC;QAAC,MAAM,CAAC;YACP,4CAA4C;QAC9C,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,uBAAuB,IAAI,KAAK,MAAM,EAAE,CAAC,CAAC;IAC5D,CAAC;IAED,OAAO,GAAG,CAAC,IAAI,EAAgB,CAAC;AAClC,CAAC;AAgCD,8EAA8E;AAC9E,aAAa;AACb,8EAA8E;AAE9E,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;IAC3B,IAAI,EAAE,QAAQ;IACd,OAAO,EAAE,OAAO;CACjB,CAAC,CAAC;AAEH,8EAA8E;AAE9E,MAAM,CAAC,IAAI,CACT,iBAAiB,EACjB,4EAA4E;IAC1E,0DAA0D,EAC5D;IACE,YAAY,EAAE,CAAC;SACZ,MAAM,EAAE;SACR,GAAG,CAAC,CAAC,CAAC;SACN,QAAQ,CAAC,+EAA+E,CAAC;CAC7F,EACD,KAAK,EAAE,EAAE,YAAY,EAAE,EAAE,EAAE;IACzB,MAAM,IAAI,GAAG,MAAM,SAAS,CAAgB,cAAc,YAAY,EAAE,CAAC,CAAC;IAE1E,OAAO;QACL,OAAO,EAAE;YACP;gBACE,IAAI,EAAE,MAAe;gBACrB,IAAI,EAAE,IAAI,CAAC,SAAS,CAClB;oBACE,OAAO,EAAE,YAAY;oBACrB,YAAY,EAAE,IAAI,CAAC,YAAY;oBAC/B,UAAU,EAAE,IAAI,CAAC,UAAU,IAAI,QAAQ;oBACvC,GAAG,CAAC,IAAI,CAAC,UAAU,IAAI,IAAI,IAAI,EAAE,kBAAkB,EAAE,IAAI,CAAC,UAAU,EAAE,CAAC;iBACxE,EACD,IAAI,EACJ,CAAC,CACF;aACF;SACF;KACF,CAAC;AACJ,CAAC,CACF,CAAC;AAEF,6EAA6E;AAE7E,MAAM,CAAC,IAAI,CACT,eAAe,EACf,yEAAyE,EACzE,EAAE,EACF,KAAK,IAAI,EAAE;IACT,MAAM,IAAI,GAAG,MAAM,SAAS,CAA+B,cAAc,CAAC,CAAC;IAE3E,gFAAgF;IAChF,MAAM,QAAQ,GAAc,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC;QAC7C,CAAC,CAAC,IAAI;QACN,CAAC,CAAE,IAAyB,CAAC,QAAQ,IAAI,EAAE,CAAC;IAE9C,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;IAEnD,OAAO;QACL,OAAO,EAAE;YACP;gBACE,IAAI,EAAE,MAAe;gBACrB,IAAI,EAAE,IAAI,CAAC,SAAS,CAClB;oBACE,KAAK,EAAE,QAAQ,CAAC,MAAM;oBACtB,MAAM,EAAE,MAAM,CAAC,MAAM;oBACrB,QAAQ,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;wBAC7B,IAAI,EAAE,CAAC,CAAC,IAAI;wBACZ,EAAE,EAAE,CAAC,CAAC,EAAE;wBACR,SAAS,EAAE,CAAC,CAAC,SAAS;wBACtB,UAAU,EAAE,CAAC,CAAC,UAAU;qBACzB,CAAC,CAAC;iBACJ,EACD,IAAI,EACJ,CAAC,CACF;aACF;SACF;KACF,CAAC;AACJ,CAAC,CACF,CAAC;AAEF,6EAA6E;AAE7E,MAAM,CAAC,IAAI,CACT,yBAAyB,EACzB,yEAAyE;IACvE,8EAA8E;IAC9E,yDAAyD,EAC3D;IACE,YAAY,EAAE,CAAC;SACZ,MAAM,EAAE;SACR,GAAG,CAAC,CAAC,CAAC;SACN,QAAQ,CAAC,4DAA4D,CAAC;CAC1E,EACD,KAAK,EAAE,EAAE,YAAY,EAAE,EAAE,EAAE;IACzB,+EAA+E;IAC/E,4DAA4D;IAC5D,6FAA6F;IAC7F,iFAAiF;IAEjF,MAAM,IAAI,GAAqB;QAC7B,YAAY;QACZ,KAAK,EAAE,IAAI;QACX,UAAU,EAAE,SAAS;QACrB,oBAAoB,EAAE,SAAS;QAC/B,IAAI,EAAE,2FAA2F;KAClG,CAAC;IAEF,OAAO;QACL,OAAO,EAAE;YACP;gBACE,IAAI,EAAE,MAAe;gBACrB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;aACpC;SACF;KACF,CAAC;AACJ,CAAC,CACF,CAAC;AAEF,8EAA8E;AAC9E,QAAQ;AACR,8EAA8E;AAE9E,KAAK,UAAU,IAAI;IACjB,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAChC,OAAO,CAAC,KAAK,CAAC,sCAAsC,CAAC,CAAC;AACxD,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IACnB,OAAO,CAAC,KAAK,CAAC,2BAA2B,EAAE,GAAG,CAAC,CAAC;IAChD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@clavisagent/mcp-server",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "MCP server for secure credential management. Handles encrypted storage, auto token refresh, and rate limiting for Claude Desktop and AI agents.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"author": "Clavis",
|
|
7
|
+
"license": "MIT",
|
|
8
|
+
"homepage": "https://clavisagent.com",
|
|
9
|
+
"keywords": [
|
|
10
|
+
"mcp",
|
|
11
|
+
"model-context-protocol",
|
|
12
|
+
"claude",
|
|
13
|
+
"anthropic",
|
|
14
|
+
"credentials",
|
|
15
|
+
"authentication",
|
|
16
|
+
"api-keys",
|
|
17
|
+
"oauth",
|
|
18
|
+
"token-refresh",
|
|
19
|
+
"rate-limiting",
|
|
20
|
+
"ai-agents",
|
|
21
|
+
"security"
|
|
22
|
+
],
|
|
23
|
+
"bin": {
|
|
24
|
+
"clavis-mcp": "./dist/index.js"
|
|
25
|
+
},
|
|
26
|
+
"main": "./dist/index.js",
|
|
27
|
+
"files": [
|
|
28
|
+
"dist/",
|
|
29
|
+
"README.md",
|
|
30
|
+
"LICENSE"
|
|
31
|
+
],
|
|
32
|
+
"scripts": {
|
|
33
|
+
"build": "tsc",
|
|
34
|
+
"dev": "tsc --watch",
|
|
35
|
+
"start": "node dist/index.js"
|
|
36
|
+
},
|
|
37
|
+
"dependencies": {
|
|
38
|
+
"@modelcontextprotocol/sdk": "^1.9.0",
|
|
39
|
+
"zod": "^3.23.8"
|
|
40
|
+
},
|
|
41
|
+
"devDependencies": {
|
|
42
|
+
"@types/node": "^22.0.0",
|
|
43
|
+
"typescript": "^5.5.0"
|
|
44
|
+
},
|
|
45
|
+
"engines": {
|
|
46
|
+
"node": ">=18"
|
|
47
|
+
}
|
|
48
|
+
}
|