@l4yercak3/cli 1.1.11 → 1.2.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.
@@ -0,0 +1,162 @@
1
+ /**
2
+ * MCP Tool Registry
3
+ *
4
+ * Central registry for all MCP tools organized by domain.
5
+ * Handles tool discovery, filtering by auth context, and execution.
6
+ *
7
+ * @module mcp/registry
8
+ */
9
+
10
+ const { requireAuth, hasPermission } = require('../auth');
11
+
12
+ // Import tool domains
13
+ const coreDomain = require('./domains/core');
14
+ const crmDomain = require('./domains/crm');
15
+ const eventsDomain = require('./domains/events');
16
+ const formsDomain = require('./domains/forms');
17
+ const codegenDomain = require('./domains/codegen');
18
+ const applicationsDomain = require('./domains/applications');
19
+
20
+ /**
21
+ * @typedef {Object} ToolDefinition
22
+ * @property {string} name - Tool name (e.g., 'l4yercak3_get_capabilities')
23
+ * @property {string} description - Human-readable description
24
+ * @property {Object} inputSchema - JSON Schema for tool parameters
25
+ * @property {Function} handler - Async function(params, authContext) => result
26
+ * @property {boolean} requiresAuth - Whether auth is required
27
+ * @property {string[]} [requiredPermissions] - Permissions needed to use this tool
28
+ */
29
+
30
+ /**
31
+ * @typedef {Object} ToolDomain
32
+ * @property {string} name - Domain name (e.g., 'crm')
33
+ * @property {string} description - Domain description
34
+ * @property {ToolDefinition[]} tools - Tools in this domain
35
+ */
36
+
37
+ /**
38
+ * All registered tool domains
39
+ * @type {ToolDomain[]}
40
+ */
41
+ const toolDomains = [
42
+ coreDomain,
43
+ applicationsDomain,
44
+ crmDomain,
45
+ eventsDomain,
46
+ formsDomain,
47
+ codegenDomain,
48
+ ];
49
+
50
+ /**
51
+ * Get all available tools for the current auth context
52
+ *
53
+ * @param {Object|null} authContext - Current auth context
54
+ * @returns {ToolDefinition[]} Available tools
55
+ */
56
+ function getAvailableTools(authContext) {
57
+ const tools = [];
58
+
59
+ for (const domain of toolDomains) {
60
+ for (const tool of domain.tools) {
61
+ // Include if no auth required
62
+ if (!tool.requiresAuth) {
63
+ tools.push(tool);
64
+ continue;
65
+ }
66
+
67
+ // Skip if auth required but not authenticated
68
+ if (!authContext) {
69
+ continue;
70
+ }
71
+
72
+ // Check required permissions
73
+ if (tool.requiredPermissions && tool.requiredPermissions.length > 0) {
74
+ const hasAllPermissions = tool.requiredPermissions.every(perm =>
75
+ hasPermission(authContext, perm)
76
+ );
77
+ if (!hasAllPermissions) {
78
+ continue;
79
+ }
80
+ }
81
+
82
+ tools.push(tool);
83
+ }
84
+ }
85
+
86
+ return tools;
87
+ }
88
+
89
+ /**
90
+ * Find a tool by name
91
+ *
92
+ * @param {string} name - Tool name
93
+ * @returns {ToolDefinition|null}
94
+ */
95
+ function findTool(name) {
96
+ for (const domain of toolDomains) {
97
+ const tool = domain.tools.find(t => t.name === name);
98
+ if (tool) {
99
+ return tool;
100
+ }
101
+ }
102
+ return null;
103
+ }
104
+
105
+ /**
106
+ * Execute a tool
107
+ *
108
+ * @param {string} name - Tool name
109
+ * @param {Object} params - Tool parameters
110
+ * @param {Object|null} authContext - Current auth context
111
+ * @returns {Promise<any>} Tool result
112
+ */
113
+ async function executeTool(name, params, authContext) {
114
+ const tool = findTool(name);
115
+
116
+ if (!tool) {
117
+ throw new Error(`Unknown tool: ${name}`);
118
+ }
119
+
120
+ // Check auth requirements
121
+ if (tool.requiresAuth) {
122
+ requireAuth(authContext);
123
+
124
+ // Check permissions
125
+ if (tool.requiredPermissions && tool.requiredPermissions.length > 0) {
126
+ for (const perm of tool.requiredPermissions) {
127
+ if (!hasPermission(authContext, perm)) {
128
+ throw new Error(
129
+ `Permission denied: ${perm} required for tool ${name}`
130
+ );
131
+ }
132
+ }
133
+ }
134
+ }
135
+
136
+ // Execute the tool
137
+ try {
138
+ return await tool.handler(params, authContext);
139
+ } catch (error) {
140
+ // Re-throw with context
141
+ const enhancedError = new Error(`Tool ${name} failed: ${error.message}`);
142
+ enhancedError.toolName = name;
143
+ enhancedError.originalError = error;
144
+ throw enhancedError;
145
+ }
146
+ }
147
+
148
+ /**
149
+ * Get all domains (for documentation/discovery)
150
+ *
151
+ * @returns {ToolDomain[]}
152
+ */
153
+ function getDomains() {
154
+ return toolDomains;
155
+ }
156
+
157
+ module.exports = {
158
+ getAvailableTools,
159
+ findTool,
160
+ executeTool,
161
+ getDomains,
162
+ };
@@ -0,0 +1,116 @@
1
+ /**
2
+ * L4YERCAK3 MCP Server
3
+ *
4
+ * Exposes L4YERCAK3 backend capabilities to Claude Code via MCP protocol.
5
+ * This allows Claude Code to discover and use L4YERCAK3 features to help
6
+ * users integrate their projects.
7
+ *
8
+ * Usage:
9
+ * - Users add via: claude mcp add l4yercak3 -- npx l4yercak3 mcp-server
10
+ * - Reads auth from ~/.l4yercak3/config.json (created by l4yercak3 login)
11
+ *
12
+ * @module mcp/server
13
+ */
14
+
15
+ const { Server } = require('@modelcontextprotocol/sdk/server/index.js');
16
+ const { StdioServerTransport } = require('@modelcontextprotocol/sdk/server/stdio.js');
17
+ const {
18
+ CallToolRequestSchema,
19
+ ListToolsRequestSchema,
20
+ } = require('@modelcontextprotocol/sdk/types.js');
21
+
22
+ const { getAuthContext } = require('./auth');
23
+ const { getAvailableTools, executeTool } = require('./registry');
24
+
25
+ /**
26
+ * Create and configure the MCP server
27
+ */
28
+ function createServer() {
29
+ const server = new Server(
30
+ {
31
+ name: 'l4yercak3',
32
+ version: require('../../package.json').version,
33
+ },
34
+ {
35
+ capabilities: {
36
+ tools: {},
37
+ },
38
+ }
39
+ );
40
+
41
+ // Handle ListTools request
42
+ server.setRequestHandler(ListToolsRequestSchema, async () => {
43
+ const authContext = await getAuthContext();
44
+ const tools = getAvailableTools(authContext);
45
+
46
+ return {
47
+ tools: tools.map(tool => ({
48
+ name: tool.name,
49
+ description: tool.description,
50
+ inputSchema: tool.inputSchema,
51
+ })),
52
+ };
53
+ });
54
+
55
+ // Handle CallTool request
56
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
57
+ const { name, arguments: args } = request.params;
58
+
59
+ try {
60
+ const authContext = await getAuthContext();
61
+ const result = await executeTool(name, args || {}, authContext);
62
+
63
+ return {
64
+ content: [
65
+ {
66
+ type: 'text',
67
+ text: typeof result === 'string' ? result : JSON.stringify(result, null, 2),
68
+ },
69
+ ],
70
+ };
71
+ } catch (error) {
72
+ return {
73
+ content: [
74
+ {
75
+ type: 'text',
76
+ text: `Error: ${error.message}`,
77
+ },
78
+ ],
79
+ isError: true,
80
+ };
81
+ }
82
+ });
83
+
84
+ return server;
85
+ }
86
+
87
+ /**
88
+ * Start the MCP server
89
+ */
90
+ async function startServer() {
91
+ const server = createServer();
92
+ const transport = new StdioServerTransport();
93
+
94
+ await server.connect(transport);
95
+
96
+ // Log startup to stderr (stdout is used for MCP protocol)
97
+ console.error('[L4YERCAK3 MCP] Server started');
98
+
99
+ // Handle graceful shutdown
100
+ process.on('SIGINT', async () => {
101
+ console.error('[L4YERCAK3 MCP] Shutting down...');
102
+ await server.close();
103
+ process.exit(0);
104
+ });
105
+
106
+ process.on('SIGTERM', async () => {
107
+ console.error('[L4YERCAK3 MCP] Shutting down...');
108
+ await server.close();
109
+ process.exit(0);
110
+ });
111
+ }
112
+
113
+ module.exports = {
114
+ createServer,
115
+ startServer,
116
+ };