ai-cred 1.0.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.
Files changed (64) hide show
  1. package/dist/cli/commands/add.d.ts +8 -0
  2. package/dist/cli/commands/add.js +145 -0
  3. package/dist/cli/commands/add.js.map +1 -0
  4. package/dist/cli/commands/get.d.ts +7 -0
  5. package/dist/cli/commands/get.js +53 -0
  6. package/dist/cli/commands/get.js.map +1 -0
  7. package/dist/cli/commands/list.d.ts +7 -0
  8. package/dist/cli/commands/list.js +118 -0
  9. package/dist/cli/commands/list.js.map +1 -0
  10. package/dist/cli/commands/remove.d.ts +7 -0
  11. package/dist/cli/commands/remove.js +53 -0
  12. package/dist/cli/commands/remove.js.map +1 -0
  13. package/dist/cli/commands/update.d.ts +8 -0
  14. package/dist/cli/commands/update.js +140 -0
  15. package/dist/cli/commands/update.js.map +1 -0
  16. package/dist/cli/index.d.ts +7 -0
  17. package/dist/cli/index.js +25 -0
  18. package/dist/cli/index.js.map +1 -0
  19. package/dist/cli/utils/display.d.ts +14 -0
  20. package/dist/cli/utils/display.js +31 -0
  21. package/dist/cli/utils/display.js.map +1 -0
  22. package/dist/cli/utils/prompt.d.ts +6 -0
  23. package/dist/cli/utils/prompt.js +66 -0
  24. package/dist/cli/utils/prompt.js.map +1 -0
  25. package/dist/core/audit-logger.d.ts +25 -0
  26. package/dist/core/audit-logger.js +41 -0
  27. package/dist/core/audit-logger.js.map +1 -0
  28. package/dist/core/audit-logger.test.d.ts +1 -0
  29. package/dist/core/audit-logger.test.js +89 -0
  30. package/dist/core/audit-logger.test.js.map +1 -0
  31. package/dist/core/errors.d.ts +23 -0
  32. package/dist/core/errors.js +78 -0
  33. package/dist/core/errors.js.map +1 -0
  34. package/dist/core/keychain-adapter.d.ts +65 -0
  35. package/dist/core/keychain-adapter.js +221 -0
  36. package/dist/core/keychain-adapter.js.map +1 -0
  37. package/dist/core/keychain-adapter.test.d.ts +1 -0
  38. package/dist/core/keychain-adapter.test.js +331 -0
  39. package/dist/core/keychain-adapter.test.js.map +1 -0
  40. package/dist/e2e/environment-isolation.test.d.ts +1 -0
  41. package/dist/e2e/environment-isolation.test.js +112 -0
  42. package/dist/e2e/environment-isolation.test.js.map +1 -0
  43. package/dist/server/index.d.ts +7 -0
  44. package/dist/server/index.js +26 -0
  45. package/dist/server/index.js.map +1 -0
  46. package/dist/server/tools.d.ts +10 -0
  47. package/dist/server/tools.js +230 -0
  48. package/dist/server/tools.js.map +1 -0
  49. package/dist/server/tools.test.d.ts +7 -0
  50. package/dist/server/tools.test.js +606 -0
  51. package/dist/server/tools.test.js.map +1 -0
  52. package/dist/types/credential.d.ts +77 -0
  53. package/dist/types/credential.js +46 -0
  54. package/dist/types/credential.js.map +1 -0
  55. package/dist/types/credential.test.d.ts +1 -0
  56. package/dist/types/credential.test.js +316 -0
  57. package/dist/types/credential.test.js.map +1 -0
  58. package/dist/utils/validation.d.ts +15 -0
  59. package/dist/utils/validation.js +34 -0
  60. package/dist/utils/validation.js.map +1 -0
  61. package/dist/utils/validation.test.d.ts +1 -0
  62. package/dist/utils/validation.test.js +139 -0
  63. package/dist/utils/validation.test.js.map +1 -0
  64. package/package.json +35 -0
@@ -0,0 +1,112 @@
1
+ import { describe, it, expect, beforeAll, afterAll } from 'vitest';
2
+ import { existsSync } from 'node:fs';
3
+ import { mkdtempSync } from 'node:fs';
4
+ import { tmpdir } from 'node:os';
5
+ import { join } from 'node:path';
6
+ import { KeychainAdapter, KeychainError } from '../core/keychain-adapter.js';
7
+ const SECURITY_BINARY = '/usr/bin/security';
8
+ const hasSecurityBinary = existsSync(SECURITY_BINARY);
9
+ describe.skipIf(!hasSecurityBinary)('E2E: Environment Isolation', () => {
10
+ let adapter;
11
+ let keychainPath;
12
+ beforeAll(async () => {
13
+ const tempDir = mkdtempSync(join(tmpdir(), 'ai-cred-e2e-'));
14
+ keychainPath = join(tempDir, 'ai-cred-e2e-test.keychain-db');
15
+ adapter = new KeychainAdapter(keychainPath);
16
+ await adapter.initialize();
17
+ });
18
+ afterAll(async () => {
19
+ try {
20
+ await adapter.destroy();
21
+ }
22
+ catch {
23
+ // Keychain may already be cleaned up
24
+ }
25
+ });
26
+ it('prod and staging credentials are isolated', async () => {
27
+ await adapter.store('prod', 'jenkins', {
28
+ type: 'jenkins',
29
+ url: 'https://prod.ci.com',
30
+ username: 'admin',
31
+ apiToken: 'prod-token-123',
32
+ });
33
+ await adapter.store('staging', 'jenkins', {
34
+ type: 'jenkins',
35
+ url: 'https://staging.ci.com',
36
+ username: 'deploy',
37
+ apiToken: 'staging-token-456',
38
+ });
39
+ const prodCred = await adapter.get('prod', 'jenkins');
40
+ expect(prodCred.type).toBe('jenkins');
41
+ if (prodCred.type === 'jenkins') {
42
+ expect(prodCred.url).toBe('https://prod.ci.com');
43
+ expect(prodCred.apiToken).toBe('prod-token-123');
44
+ // Prod NEVER returns staging data
45
+ expect(prodCred.url).not.toBe('https://staging.ci.com');
46
+ expect(prodCred.apiToken).not.toBe('staging-token-456');
47
+ }
48
+ const stagingCred = await adapter.get('staging', 'jenkins');
49
+ expect(stagingCred.type).toBe('jenkins');
50
+ if (stagingCred.type === 'jenkins') {
51
+ expect(stagingCred.url).toBe('https://staging.ci.com');
52
+ expect(stagingCred.apiToken).toBe('staging-token-456');
53
+ // Staging NEVER returns prod data
54
+ expect(stagingCred.url).not.toBe('https://prod.ci.com');
55
+ expect(stagingCred.apiToken).not.toBe('prod-token-123');
56
+ }
57
+ });
58
+ it('deleting one environment does not affect the other', async () => {
59
+ // Ensure both exist
60
+ await adapter.store('prod', 'jenkins', {
61
+ type: 'jenkins',
62
+ url: 'https://prod.ci.com',
63
+ username: 'admin',
64
+ apiToken: 'prod-token-123',
65
+ });
66
+ await adapter.store('staging', 'jenkins', {
67
+ type: 'jenkins',
68
+ url: 'https://staging.ci.com',
69
+ username: 'deploy',
70
+ apiToken: 'staging-token-456',
71
+ });
72
+ // Delete staging
73
+ await adapter.delete('staging', 'jenkins');
74
+ // Prod still accessible
75
+ const prodCred = await adapter.get('prod', 'jenkins');
76
+ expect(prodCred.type).toBe('jenkins');
77
+ if (prodCred.type === 'jenkins') {
78
+ expect(prodCred.url).toBe('https://prod.ci.com');
79
+ }
80
+ // Staging is gone
81
+ await expect(adapter.get('staging', 'jenkins')).rejects.toThrow(KeychainError);
82
+ try {
83
+ await adapter.get('staging', 'jenkins');
84
+ }
85
+ catch (err) {
86
+ expect(err).toBeInstanceOf(KeychainError);
87
+ expect(err.exitCode).toBe(44);
88
+ }
89
+ });
90
+ it('list shows both environments as separate entries', async () => {
91
+ // Store both
92
+ await adapter.store('prod', 'jenkins', {
93
+ type: 'jenkins',
94
+ url: 'https://prod.ci.com',
95
+ username: 'admin',
96
+ apiToken: 'prod-token-123',
97
+ });
98
+ await adapter.store('staging', 'jenkins', {
99
+ type: 'jenkins',
100
+ url: 'https://staging.ci.com',
101
+ username: 'deploy',
102
+ apiToken: 'staging-token-456',
103
+ });
104
+ const entries = await adapter.list();
105
+ const jenkinsEntries = entries.filter((e) => e.service === 'jenkins');
106
+ expect(jenkinsEntries.length).toBeGreaterThanOrEqual(2);
107
+ const environments = jenkinsEntries.map((e) => e.environment).sort();
108
+ expect(environments).toContain('prod');
109
+ expect(environments).toContain('staging');
110
+ });
111
+ });
112
+ //# sourceMappingURL=environment-isolation.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"environment-isolation.test.js","sourceRoot":"","sources":["../../src/e2e/environment-isolation.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * MCP Server entry point for ai-cred.
3
+ *
4
+ * Starts an MCP server over stdio transport with all credential management tools.
5
+ * CRITICAL: No console.log() -- stdio is the JSON-RPC channel.
6
+ */
7
+ export {};
@@ -0,0 +1,26 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * MCP Server entry point for ai-cred.
4
+ *
5
+ * Starts an MCP server over stdio transport with all credential management tools.
6
+ * CRITICAL: No console.log() -- stdio is the JSON-RPC channel.
7
+ */
8
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
9
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
10
+ import { registerTools } from './tools.js';
11
+ (async function main() {
12
+ try {
13
+ const server = new McpServer({
14
+ name: 'ai-cred',
15
+ version: '1.0.0',
16
+ });
17
+ registerTools(server);
18
+ const transport = new StdioServerTransport();
19
+ await server.connect(transport);
20
+ }
21
+ catch (err) {
22
+ console.error('ai-cred MCP server fatal error:', err);
23
+ process.exit(1);
24
+ }
25
+ })();
26
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAE3C,CAAC,KAAK,UAAU,IAAI;IAClB,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;YAC3B,IAAI,EAAE,SAAS;YACf,OAAO,EAAE,OAAO;SACjB,CAAC,CAAC;QAEH,aAAa,CAAC,MAAM,CAAC,CAAC;QAEtB,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;QAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAClC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,iCAAiC,EAAE,GAAG,CAAC,CAAC;QACtD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CAAC,EAAE,CAAC"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * MCP tool registrations for ai-cred credential management.
3
+ *
4
+ * All five tools: store_credential, get_credential, list_credentials, delete_credential, find_credential.
5
+ *
6
+ * CRITICAL: No console.log() anywhere -- stdio is the JSON-RPC channel.
7
+ * All errors are returned as text content, never thrown.
8
+ */
9
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
10
+ export declare function registerTools(server: McpServer): void;
@@ -0,0 +1,230 @@
1
+ /**
2
+ * MCP tool registrations for ai-cred credential management.
3
+ *
4
+ * All five tools: store_credential, get_credential, list_credentials, delete_credential, find_credential.
5
+ *
6
+ * CRITICAL: No console.log() anywhere -- stdio is the JSON-RPC channel.
7
+ * All errors are returned as text content, never thrown.
8
+ */
9
+ import { z } from 'zod';
10
+ import { KeychainAdapter, KeychainError } from '../core/keychain-adapter.js';
11
+ import { CredentialSchema } from '../types/credential.js';
12
+ import { ServiceNameSchema } from '../utils/validation.js';
13
+ import { auditLog } from '../core/audit-logger.js';
14
+ const adapter = new KeychainAdapter();
15
+ let initialized = false;
16
+ async function ensureInitialized() {
17
+ if (!initialized) {
18
+ await adapter.initialize();
19
+ initialized = true;
20
+ }
21
+ }
22
+ function errorResult(message) {
23
+ return { content: [{ type: 'text', text: message }], isError: true };
24
+ }
25
+ function textResult(message) {
26
+ return { content: [{ type: 'text', text: message }] };
27
+ }
28
+ export function registerTools(server) {
29
+ // -------------------------------------------------------------------------
30
+ // Tool 1: store_credential (MCP-02)
31
+ // -------------------------------------------------------------------------
32
+ server.registerTool('store_credential', {
33
+ description: 'Store a credential in the macOS Keychain',
34
+ inputSchema: {
35
+ service: z.string().describe('Service name (letters, numbers, hyphens, underscores)'),
36
+ environment: z.enum(['prod', 'dev', 'staging', 'global']).describe('Target environment'),
37
+ type: z.enum(['ssh', 'jenkins', 'portainer', 'aws', 'api-key']).describe('Credential type'),
38
+ // SSH fields
39
+ host: z.string().optional().describe('SSH host'),
40
+ port: z.number().optional().describe('SSH port (default 22)'),
41
+ username: z.string().optional().describe('Username for SSH or Jenkins'),
42
+ password: z.string().optional().describe('Password for SSH'),
43
+ keyPath: z.string().optional().describe('SSH key path'),
44
+ // Jenkins / Portainer fields
45
+ url: z.string().optional().describe('URL for Jenkins, Portainer, or API key'),
46
+ apiToken: z.string().optional().describe('API token for Jenkins or Portainer'),
47
+ // AWS fields
48
+ accessKeyId: z.string().optional().describe('AWS access key ID'),
49
+ secretAccessKey: z.string().optional().describe('AWS secret access key'),
50
+ region: z.string().optional().describe('AWS region'),
51
+ profile: z.string().optional().describe('AWS profile name'),
52
+ // API key fields
53
+ key: z.string().optional().describe('API key value'),
54
+ notes: z.string().optional().describe('Optional notes'),
55
+ },
56
+ }, async ({ service, environment, type, ...fields }) => {
57
+ try {
58
+ await ensureInitialized();
59
+ // Validate service name
60
+ const serviceResult = ServiceNameSchema.safeParse(service);
61
+ if (!serviceResult.success) {
62
+ return errorResult(`Invalid service name: ${serviceResult.error.issues[0]?.message ?? 'validation failed'}`);
63
+ }
64
+ // Build credential object, removing undefined keys
65
+ const credentialObj = { type };
66
+ for (const [k, v] of Object.entries(fields)) {
67
+ if (v !== undefined) {
68
+ credentialObj[k] = v;
69
+ }
70
+ }
71
+ // Validate with CredentialSchema
72
+ const result = CredentialSchema.safeParse(credentialObj);
73
+ if (!result.success) {
74
+ return errorResult(`Invalid credential: ${result.error.issues.map((i) => i.message).join(', ')}`);
75
+ }
76
+ await adapter.store(environment, service, result.data);
77
+ await auditLog({ operation: 'store', service, environment });
78
+ return textResult(`Stored ${type} credential '${service}' in ${environment}`);
79
+ }
80
+ catch (err) {
81
+ if (err instanceof KeychainError) {
82
+ return errorResult(err.message);
83
+ }
84
+ return errorResult('Unexpected error storing credential');
85
+ }
86
+ });
87
+ // -------------------------------------------------------------------------
88
+ // Tool 2: get_credential (MCP-03, META-01)
89
+ // -------------------------------------------------------------------------
90
+ server.registerTool('get_credential', {
91
+ description: 'Retrieve a credential from the macOS Keychain',
92
+ inputSchema: {
93
+ service: z.string().describe('Service name'),
94
+ environment: z.enum(['prod', 'dev', 'staging', 'global']).describe('Target environment'),
95
+ },
96
+ }, async ({ service, environment }) => {
97
+ try {
98
+ await ensureInitialized();
99
+ const credential = await adapter.get(environment, service);
100
+ // META-01: Re-store to bump macOS mdat timestamp (last-accessed tracking)
101
+ await adapter.store(environment, service, credential);
102
+ await auditLog({ operation: 'get', service, environment });
103
+ return textResult(JSON.stringify(credential, null, 2));
104
+ }
105
+ catch (err) {
106
+ if (err instanceof KeychainError) {
107
+ if (err.exitCode === 44) {
108
+ return errorResult(`No credential found for '${service}' in ${environment}`);
109
+ }
110
+ return errorResult(err.message);
111
+ }
112
+ return errorResult('Unexpected error retrieving credential');
113
+ }
114
+ });
115
+ // -------------------------------------------------------------------------
116
+ // Tool 3: list_credentials (MCP-04)
117
+ // -------------------------------------------------------------------------
118
+ server.registerTool('list_credentials', {
119
+ description: 'List all stored credentials (metadata only, no secrets)',
120
+ inputSchema: {
121
+ environment: z.enum(['prod', 'dev', 'staging', 'global']).optional().describe('Filter by environment (optional)'),
122
+ },
123
+ }, async ({ environment }) => {
124
+ try {
125
+ await ensureInitialized();
126
+ let items = await adapter.list();
127
+ if (environment) {
128
+ items = items.filter((i) => i.environment === environment);
129
+ }
130
+ if (items.length === 0) {
131
+ return textResult('No credentials found');
132
+ }
133
+ // Fetch notes per item (notes are in the credential blob, not metadata)
134
+ const notesMap = new Map();
135
+ for (const item of items) {
136
+ try {
137
+ const cred = await adapter.get(item.environment, item.service);
138
+ if (cred && 'notes' in cred && cred.notes) {
139
+ notesMap.set(`${item.environment}/${item.service}`, cred.notes);
140
+ }
141
+ }
142
+ catch {
143
+ // Skip if can't fetch — notes just won't show
144
+ }
145
+ }
146
+ // Format as text table
147
+ const header = 'Service | Environment | Type | Created | Last Accessed | Notes';
148
+ const divider = '---------------- | ----------- | ---------- | -------------------- | -------------------- | -----';
149
+ const rows = items.map((i) => {
150
+ const svc = i.service.padEnd(16);
151
+ const env = i.environment.padEnd(11);
152
+ const typ = i.type.padEnd(10);
153
+ const cre = (i.createdAt || 'N/A').padEnd(20);
154
+ const mod = (i.modifiedAt || 'N/A').padEnd(20);
155
+ const notes = notesMap.get(`${i.environment}/${i.service}`) || '';
156
+ return `${svc} | ${env} | ${typ} | ${cre} | ${mod} | ${notes}`;
157
+ });
158
+ const table = [header, divider, ...rows].join('\n');
159
+ await auditLog({ operation: 'list', service: '*', environment: environment ?? '*' });
160
+ return textResult(table);
161
+ }
162
+ catch (err) {
163
+ if (err instanceof KeychainError) {
164
+ return errorResult(err.message);
165
+ }
166
+ return errorResult('Unexpected error listing credentials');
167
+ }
168
+ });
169
+ // -------------------------------------------------------------------------
170
+ // Tool 4: delete_credential (MCP-05)
171
+ // -------------------------------------------------------------------------
172
+ server.registerTool('delete_credential', {
173
+ description: 'Delete a credential from the macOS Keychain',
174
+ inputSchema: {
175
+ service: z.string().describe('Service name'),
176
+ environment: z.enum(['prod', 'dev', 'staging', 'global']).describe('Target environment'),
177
+ },
178
+ }, async ({ service, environment }) => {
179
+ try {
180
+ await ensureInitialized();
181
+ await adapter.delete(environment, service);
182
+ await auditLog({ operation: 'delete', service, environment });
183
+ return textResult(`Deleted credential '${service}' from ${environment}`);
184
+ }
185
+ catch (err) {
186
+ if (err instanceof KeychainError) {
187
+ if (err.exitCode === 44) {
188
+ return errorResult(`No credential found for '${service}' in ${environment}`);
189
+ }
190
+ return errorResult(err.message);
191
+ }
192
+ return errorResult('Unexpected error deleting credential');
193
+ }
194
+ });
195
+ // -------------------------------------------------------------------------
196
+ // Tool 5: find_credential (MCP-06)
197
+ // -------------------------------------------------------------------------
198
+ server.registerTool('find_credential', {
199
+ description: 'Search credentials by partial service name (case-insensitive substring match)',
200
+ inputSchema: {
201
+ query: z.string().min(1).describe('Partial service name to search for'),
202
+ environment: z.enum(['prod', 'dev', 'staging', 'global']).optional()
203
+ .describe('Filter by environment (optional)'),
204
+ },
205
+ }, async ({ query, environment }) => {
206
+ try {
207
+ await ensureInitialized();
208
+ let items = await adapter.list();
209
+ // Case-insensitive substring match on service name
210
+ items = items.filter((item) => item.service.toLowerCase().includes(query.toLowerCase()));
211
+ // Optional environment filter
212
+ if (environment) {
213
+ items = items.filter((item) => item.environment === environment);
214
+ }
215
+ if (items.length === 0) {
216
+ return textResult(`No credentials matching '${query}'`);
217
+ }
218
+ const lines = items.map((item) => `${item.service} (${item.environment}) [${item.type}]`);
219
+ await auditLog({ operation: 'find', service: query, environment: environment ?? '*' });
220
+ return textResult(lines.join('\n'));
221
+ }
222
+ catch (err) {
223
+ if (err instanceof KeychainError) {
224
+ return errorResult(err.message);
225
+ }
226
+ return errorResult('Unexpected error searching credentials');
227
+ }
228
+ });
229
+ }
230
+ //# sourceMappingURL=tools.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tools.js","sourceRoot":"","sources":["../../src/server/tools.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Integration tests for MCP tool handlers.
3
+ *
4
+ * Uses the MCP Client + InMemoryTransport to invoke tools end-to-end,
5
+ * plus direct KeychainAdapter tests for META-01 timestamp verification.
6
+ */
7
+ export {};