@edicarlos.lds/businessmap-mcp 2.1.1 → 2.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.
package/README.md CHANGED
@@ -249,11 +249,28 @@ You can run the server as a remote MCP endpoint over Streamable HTTP. This is us
249
249
  npm start
250
250
  ```
251
251
 
252
- 2. **Connect your client:**
253
-
254
252
  Configure your MCP client to connect to the Streamable HTTP endpoint:
255
253
  - **URL**: `http://your-server:3000/mcp`
256
254
 
255
+ ### Programmatic & Middleware Usage
256
+
257
+ If you import this package programmatically or want to add authentication/security (like rate-limiting) to your HTTP endpoint, you can inject custom Express middlewares:
258
+
259
+ ```typescript
260
+ import { startHttpServer } from '@edicarlos.lds/businessmap-mcp';
261
+
262
+ await startHttpServer({
263
+ middlewares: [
264
+ (req, res, next) => {
265
+ // Your custom authentication/authorization logic here
266
+ next();
267
+ }
268
+ ]
269
+ });
270
+ ```
271
+
272
+ For detailed examples (including static API Keys, JWT verification, and rate limiting), see the [Programmatic Middleware Guide](docs/MIDDLEWARE.md).
273
+
257
274
  ### Manual Setup
258
275
 
259
276
  1. Clone this repository:
package/dist/index.d.ts CHANGED
@@ -1,3 +1,4 @@
1
1
  #!/usr/bin/env node
2
- export {};
2
+ export { startHttpServer, HttpServerOptions } from './server/http.js';
3
+ export { BusinessMapMcpServer } from './server/mcp-server.js';
3
4
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AASA,OAAO,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACtE,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC"}
package/dist/index.js CHANGED
@@ -1,8 +1,12 @@
1
1
  #!/usr/bin/env node
2
+ import { fileURLToPath } from 'node:url';
3
+ import fs from 'node:fs';
2
4
  import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
3
5
  import { config, validateConfig } from './config/environment.js';
4
6
  import { BusinessMapMcpServer } from './server/mcp-server.js';
5
7
  import { logger } from './utils/logger.js';
8
+ export { startHttpServer } from './server/http.js';
9
+ export { BusinessMapMcpServer } from './server/mcp-server.js';
6
10
  async function initializeWithRetry(server) {
7
11
  logger.info('šŸ”„ Initializing connection to BusinessMap API...');
8
12
  let retryCount = 0;
@@ -61,21 +65,34 @@ async function main() {
61
65
  process.exit(1);
62
66
  }
63
67
  }
64
- // Handle graceful shutdown
65
- process.on('SIGINT', () => {
66
- logger.info('\nšŸ›‘ Shutting down BusinessMap MCP Server...');
67
- process.exit(0);
68
- });
69
- process.on('SIGTERM', () => {
70
- logger.info('\nšŸ›‘ Shutting down BusinessMap MCP Server...');
71
- process.exit(0);
72
- });
73
- // Start the server
74
- try {
75
- await main();
76
- }
77
- catch (error) {
78
- console.error('šŸ’„ Unhandled error:', error);
79
- process.exit(1);
68
+ // Check if run directly
69
+ const getRealpath = (p) => {
70
+ try {
71
+ return fs.realpathSync(p);
72
+ }
73
+ catch {
74
+ return p;
75
+ }
76
+ };
77
+ const isMain = process.argv[1] && (getRealpath(process.argv[1]) === fileURLToPath(import.meta.url) ||
78
+ getRealpath(process.argv[1]).replace(/\.[jt]s$/, '') === fileURLToPath(import.meta.url).replace(/\.[jt]s$/, ''));
79
+ if (isMain) {
80
+ // Handle graceful shutdown
81
+ process.on('SIGINT', () => {
82
+ logger.info('\nšŸ›‘ Shutting down BusinessMap MCP Server...');
83
+ process.exit(0);
84
+ });
85
+ process.on('SIGTERM', () => {
86
+ logger.info('\nšŸ›‘ Shutting down BusinessMap MCP Server...');
87
+ process.exit(0);
88
+ });
89
+ // Start the server
90
+ try {
91
+ await main();
92
+ }
93
+ catch (error) {
94
+ console.error('šŸ’„ Unhandled error:', error);
95
+ process.exit(1);
96
+ }
80
97
  }
81
98
  //# 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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"}
@@ -1,2 +1,7 @@
1
- export declare function startHttpServer(): Promise<void>;
1
+ import { Server } from 'node:http';
2
+ import express from 'express';
3
+ export interface HttpServerOptions {
4
+ middlewares?: express.RequestHandler[];
5
+ }
6
+ export declare function startHttpServer(options?: HttpServerOptions): Promise<Server>;
2
7
  //# sourceMappingURL=http.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../src/server/http.ts"],"names":[],"mappings":"AAyBA,wBAAsB,eAAe,kBA8IpC"}
1
+ {"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../src/server/http.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAEnC,OAAO,OAAO,MAAM,SAAS,CAAC;AAwB9B,MAAM,WAAW,iBAAiB;IAChC,WAAW,CAAC,EAAE,OAAO,CAAC,cAAc,EAAE,CAAC;CACxC;AAED,wBAAsB,eAAe,CAAC,OAAO,GAAE,iBAAsB,GAAG,OAAO,CAAC,MAAM,CAAC,CA4KtF"}
@@ -15,8 +15,10 @@ async function closeSession(id, session) {
15
15
  }
16
16
  logger.info(`MCP session closed: ${id}`);
17
17
  }
18
- export async function startHttpServer() {
18
+ export async function startHttpServer(options = {}) {
19
19
  const app = express();
20
+ // Disable X-Powered-By header to prevent disclosing version/framework info
21
+ app.disable('x-powered-by');
20
22
  // Parse JSON bodies (required for StreamableHTTP transport)
21
23
  app.use(express.json());
22
24
  // Enable CORS with configured allowed origins
@@ -26,10 +28,17 @@ export async function startHttpServer() {
26
28
  allowedHeaders: ['Content-Type', 'mcp-session-id', 'last-event-id'],
27
29
  exposedHeaders: ['mcp-session-id'],
28
30
  }));
31
+ // Apply custom middlewares (e.g. for authentication/authorization)
32
+ if (options.middlewares && options.middlewares.length > 0) {
33
+ options.middlewares.forEach((middleware) => {
34
+ app.use(middleware);
35
+ });
36
+ }
29
37
  // Request logging middleware
30
38
  app.use((req, _res, next) => {
31
39
  const sessionId = req.headers['mcp-session-id'];
32
- logger.debug(`${req.method} ${req.path}${sessionId ? ` [session: ${sessionId}]` : ''}`);
40
+ const sessionSuffix = sessionId ? ` [session: ${sessionId}]` : '';
41
+ logger.debug(`${req.method} ${req.path}${sessionSuffix}`);
33
42
  next();
34
43
  });
35
44
  const sessions = new Map();
@@ -46,74 +55,82 @@ export async function startHttpServer() {
46
55
  }, 60_000); // check every minute
47
56
  // Prevent the interval from blocking process exit
48
57
  cleanupInterval.unref();
58
+ const handleNewSession = async (req, res, logResponse, sendError) => {
59
+ const sessionServer = new BusinessMapMcpServer();
60
+ // New session: create a fresh transport
61
+ const transport = new StreamableHTTPServerTransport({
62
+ sessionIdGenerator: () => randomUUID(),
63
+ onsessioninitialized: (id) => {
64
+ sessions.set(id, { transport, server: sessionServer, lastActivityAt: Date.now() });
65
+ logger.info(`New MCP session initialized: ${id}`);
66
+ },
67
+ onsessionclosed: async (id) => {
68
+ const session = sessions.get(id);
69
+ sessions.delete(id);
70
+ if (session) {
71
+ await closeSession(id, session);
72
+ }
73
+ },
74
+ allowedHosts: config.server.allowedHosts,
75
+ allowedOrigins: config.server.allowedOrigins,
76
+ enableDnsRebindingProtection: true,
77
+ });
78
+ try {
79
+ await sessionServer.server.connect(transport);
80
+ await transport.handleRequest(req, res, req.body);
81
+ logResponse(res.statusCode);
82
+ }
83
+ catch (error) {
84
+ logger.error('Failed to handle new MCP session:', error);
85
+ try {
86
+ await sessionServer.server.close();
87
+ }
88
+ catch (closeError) {
89
+ logger.warn('Error while cleaning up failed session:', closeError);
90
+ }
91
+ if (!res.headersSent) {
92
+ sendError(500, 'Failed to initialize MCP session');
93
+ }
94
+ }
95
+ };
96
+ const handleExistingSession = async (req, res, sessionId, logResponse, sendError) => {
97
+ const session = sessions.get(sessionId);
98
+ if (!session) {
99
+ sendError(404, `Session not found: ${sessionId}`);
100
+ return;
101
+ }
102
+ session.lastActivityAt = Date.now();
103
+ try {
104
+ await session.transport.handleRequest(req, res, req.body);
105
+ logResponse(res.statusCode);
106
+ }
107
+ catch (error) {
108
+ logger.error(`Error handling request for session ${sessionId}:`, error);
109
+ if (!res.headersSent) {
110
+ sendError(500, 'Internal server error');
111
+ }
112
+ }
113
+ };
49
114
  // Single /mcp endpoint handles GET, POST and DELETE (Streamable HTTP spec 2025-03-26)
50
115
  const handleMcpRequest = async (req, res) => {
51
116
  const start = Date.now();
52
117
  const sessionId = req.headers['mcp-session-id'];
53
118
  const logResponse = (statusCode) => {
54
- logger.debug(`${req.method} ${req.path} -> ${statusCode} (${Date.now() - start}ms)${sessionId ? ` [session: ${sessionId}]` : ''}`);
119
+ const duration = Date.now() - start;
120
+ const sessionSuffix = sessionId ? ` [session: ${sessionId}]` : '';
121
+ logger.debug(`${req.method} ${req.path} -> ${statusCode} (${duration}ms)${sessionSuffix}`);
55
122
  };
56
123
  const sendError = (statusCode, message) => {
57
124
  logResponse(statusCode);
58
125
  res.status(statusCode).json({ error: message });
59
126
  };
60
127
  if (req.method === 'POST' && !sessionId) {
61
- const sessionServer = new BusinessMapMcpServer();
62
- // New session: create a fresh transport
63
- const transport = new StreamableHTTPServerTransport({
64
- sessionIdGenerator: () => randomUUID(),
65
- onsessioninitialized: (id) => {
66
- sessions.set(id, { transport, server: sessionServer, lastActivityAt: Date.now() });
67
- logger.info(`New MCP session initialized: ${id}`);
68
- },
69
- onsessionclosed: async (id) => {
70
- const session = sessions.get(id);
71
- sessions.delete(id);
72
- if (session) {
73
- await closeSession(id, session);
74
- }
75
- },
76
- allowedHosts: config.server.allowedHosts,
77
- allowedOrigins: config.server.allowedOrigins,
78
- enableDnsRebindingProtection: true,
79
- });
80
- try {
81
- await sessionServer.server.connect(transport);
82
- await transport.handleRequest(req, res, req.body);
83
- logResponse(res.statusCode);
84
- }
85
- catch (error) {
86
- logger.error('Failed to handle new MCP session:', error);
87
- try {
88
- await sessionServer.server.close();
89
- }
90
- catch (closeError) {
91
- logger.warn('Error while cleaning up failed session:', closeError);
92
- }
93
- if (!res.headersSent) {
94
- sendError(500, 'Failed to initialize MCP session');
95
- }
96
- }
128
+ await handleNewSession(req, res, logResponse, sendError);
97
129
  return;
98
130
  }
99
131
  // Existing session
100
132
  if (sessionId) {
101
- const session = sessions.get(sessionId);
102
- if (!session) {
103
- sendError(404, `Session not found: ${sessionId}`);
104
- return;
105
- }
106
- session.lastActivityAt = Date.now();
107
- try {
108
- await session.transport.handleRequest(req, res, req.body);
109
- logResponse(res.statusCode);
110
- }
111
- catch (error) {
112
- logger.error(`Error handling request for session ${sessionId}:`, error);
113
- if (!res.headersSent) {
114
- sendError(500, 'Internal server error');
115
- }
116
- }
133
+ await handleExistingSession(req, res, sessionId, logResponse, sendError);
117
134
  return;
118
135
  }
119
136
  sendError(400, 'Missing mcp-session-id header');
@@ -126,7 +143,7 @@ export async function startHttpServer() {
126
143
  res.json({ status: 'ok', version: config.server.version });
127
144
  });
128
145
  const port = config.server.port;
129
- app.listen(port, () => {
146
+ return app.listen(port, () => {
130
147
  logger.success(`HTTP Server running on port ${port}`);
131
148
  logger.info(`MCP Endpoint: http://localhost:${port}/mcp`);
132
149
  logger.info(`Health Check: http://localhost:${port}/health`);
@@ -1 +1 @@
1
- {"version":3,"file":"http.js","sourceRoot":"","sources":["../../src/server/http.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"http.js","sourceRoot":"","sources":["../../src/server/http.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,169 @@
1
+ # Logging System
2
+
3
+ ## Overview
4
+
5
+ The BusinessMap MCP Server uses a structured logging system that ensures compatibility with the Model Context Protocol (MCP) while providing clear, categorized log output.
6
+
7
+ ## Why STDERR?
8
+
9
+ The MCP protocol uses **STDOUT exclusively for JSON-RPC communication**. Any output to STDOUT that is not valid JSON-RPC will corrupt the protocol and cause errors like:
10
+
11
+ ```
12
+ MCP businessmap: Unexpected token 'āœ…', "āœ… Configur"... is not valid JSON
13
+ ```
14
+
15
+ Therefore, **all logging must go to STDERR** (`console.error` or `process.stderr.write`).
16
+
17
+ ## Logger Utility
18
+
19
+ Instead of using raw `console.error` for all messages (which can be misleading), we provide a `logger` utility that categorizes messages while still outputting to STDERR.
20
+
21
+ ### Log Levels
22
+
23
+ ```typescript
24
+ export enum LogLevel {
25
+ DEBUG = 0, // Detailed debugging information
26
+ INFO = 1, // Informational messages (default)
27
+ WARN = 2, // Warning messages
28
+ ERROR = 3, // Error messages
29
+ NONE = 4, // Disable all logging
30
+ }
31
+ ```
32
+
33
+ ### Usage Examples
34
+
35
+ ```typescript
36
+ import { logger } from './utils/logger.js';
37
+
38
+ // Success messages (shown at INFO level)
39
+ logger.success('Successfully connected to BusinessMap API');
40
+
41
+ // Informational messages (shown at INFO level)
42
+ logger.info('šŸš€ Starting BusinessMap MCP Server v1.0.0');
43
+ logger.info('šŸ“” BusinessMap API: https://account.kanbanize.com/api/v2');
44
+
45
+ // Debug messages (shown at DEBUG level only)
46
+ logger.debug('Fetching effective cycle time columns for board 123');
47
+
48
+ // Warning messages (shown at WARN level and above)
49
+ logger.warn('Direct board lookup failed, trying fallback method');
50
+
51
+ // Error messages (shown at ERROR level and above)
52
+ logger.error('Failed to connect to API', errorObject);
53
+ ```
54
+
55
+ ### Output Format
56
+
57
+ All log messages include timestamps and clear prefixes:
58
+
59
+ ```
60
+ [2025-11-15T10:30:45.123Z] āœ… SUCCESS: Successfully connected to BusinessMap API
61
+ [2025-11-15T10:30:45.456Z] ā„¹ļø INFO: šŸš€ Starting BusinessMap MCP Server v1.0.0
62
+ [2025-11-15T10:30:46.789Z] šŸ” DEBUG: Fetching effective cycle time columns for board 123
63
+ [2025-11-15T10:30:47.012Z] āš ļø WARN: Direct board lookup failed, trying fallback method
64
+ [2025-11-15T10:30:47.345Z] āŒ ERROR: Failed to connect to API
65
+ ```
66
+
67
+ ## Configuration
68
+
69
+ Set the `LOG_LEVEL` environment variable to control verbosity:
70
+
71
+ ```bash
72
+ # Show all messages including debug
73
+ LOG_LEVEL=0 npx @edicarlos.lds/businessmap-mcp
74
+
75
+ # Show info, warnings, and errors (default)
76
+ LOG_LEVEL=1 npx @edicarlos.lds/businessmap-mcp
77
+
78
+ # Show only warnings and errors
79
+ LOG_LEVEL=2 npx @edicarlos.lds/businessmap-mcp
80
+
81
+ # Show only errors
82
+ LOG_LEVEL=3 npx @edicarlos.lds/businessmap-mcp
83
+
84
+ # Disable all logging
85
+ LOG_LEVEL=4 npx @edicarlos.lds/businessmap-mcp
86
+ ```
87
+
88
+ ### In Claude Desktop Config
89
+
90
+ ```json
91
+ {
92
+ "mcpServers": {
93
+ "Businessmap": {
94
+ "command": "npx",
95
+ "args": ["-y", "@edicarlos.lds/businessmap-mcp"],
96
+ "env": {
97
+ "BUSINESSMAP_API_TOKEN": "your_token",
98
+ "BUSINESSMAP_API_URL": "https://account.kanbanize.com/api/v2",
99
+ "LOG_LEVEL": "1"
100
+ }
101
+ }
102
+ }
103
+ }
104
+ ```
105
+
106
+ ## Benefits
107
+
108
+ ### āœ… Clear Message Categorization
109
+
110
+ Instead of everything being "errors" (when using `console.error`), messages are properly categorized:
111
+
112
+ - **SUCCESS**: Operations completed successfully
113
+ - **INFO**: General informational messages
114
+ - **DEBUG**: Detailed debugging information
115
+ - **WARN**: Non-critical issues or fallback scenarios
116
+ - **ERROR**: Actual errors and failures
117
+
118
+ ### āœ… MCP Protocol Compliance
119
+
120
+ All output goes to STDERR, keeping STDOUT clean for JSON-RPC:
121
+
122
+ ```typescript
123
+ // āŒ BAD - Breaks MCP protocol
124
+ console.log('Starting server...');
125
+
126
+ // āœ… GOOD - Uses STDERR
127
+ console.error('Starting server...');
128
+
129
+ // āœ… BETTER - Categorized and uses STDERR
130
+ logger.info('Starting server...');
131
+ ```
132
+
133
+ ### āœ… Configurable Verbosity
134
+
135
+ Control what gets logged without changing code:
136
+
137
+ ```bash
138
+ # Production: minimal logging
139
+ LOG_LEVEL=2
140
+
141
+ # Development: detailed logging
142
+ LOG_LEVEL=0
143
+ ```
144
+
145
+ ### āœ… Consistent Format
146
+
147
+ All messages follow the same format with timestamps and clear prefixes, making logs easier to read and parse.
148
+
149
+ ## Migration from console.error
150
+
151
+ When migrating from `console.error` to the logger utility, choose the appropriate method:
152
+
153
+ ```typescript
154
+ // Before
155
+ console.error('āœ… Successfully connected');
156
+ console.error('šŸ”„ Retrying connection...');
157
+ console.error('āš ļø Fallback method used');
158
+ console.error('āŒ Connection failed');
159
+
160
+ // After
161
+ logger.success('Successfully connected');
162
+ logger.info('Retrying connection...');
163
+ logger.warn('Fallback method used');
164
+ logger.error('Connection failed');
165
+ ```
166
+
167
+ ## Implementation Details
168
+
169
+ The logger is implemented in `src/utils/logger.ts` and uses a singleton pattern. All methods internally call `console.error` to ensure output goes to STDERR, maintaining MCP protocol compatibility.
@@ -0,0 +1,141 @@
1
+ # Programmatic Usage & Custom Middleware Guide
2
+
3
+ This guide is designed for developers who want to embed the **BusinessMap MCP Server** programmatically into their own Node.js/TypeScript applications, and implement custom logic (such as authentication, authorization, logging, or rate-limiting) using Express middlewares.
4
+
5
+ ---
6
+
7
+ ## šŸš€ Quick Start
8
+
9
+ Ensure you have installed the package:
10
+
11
+ ```bash
12
+ npm install @edicarlos.lds/businessmap-mcp
13
+ ```
14
+
15
+ You can import `startHttpServer` and launch the MCP server in HTTP mode programmatically:
16
+
17
+ ```typescript
18
+ import { startHttpServer } from '@edicarlos.lds/businessmap-mcp';
19
+
20
+ // Start HTTP server with default options
21
+ await startHttpServer();
22
+ ```
23
+
24
+ ---
25
+
26
+ ## šŸ”’ Implementing Custom Authentication
27
+
28
+ Since the HTTP transport does not enforce authentication by default, you can inject custom Express middlewares to secure the `/mcp` endpoints.
29
+
30
+ ### Example 1: Static API Key Authentication
31
+ This middleware checks for a pre-configured header (e.g. `Authorization` or `x-api-key`).
32
+
33
+ ```typescript
34
+ import { startHttpServer } from '@edicarlos.lds/businessmap-mcp';
35
+
36
+ const API_KEY = process.env.MCP_SERVER_KEY || 'your-secret-api-key';
37
+
38
+ await startHttpServer({
39
+ middlewares: [
40
+ (req, res, next) => {
41
+ // Allow health check to remain public
42
+ if (req.path === '/health') {
43
+ return next();
44
+ }
45
+
46
+ const clientKey = req.headers['x-api-key'] || req.headers['authorization'];
47
+
48
+ if (clientKey === API_KEY || clientKey === `Bearer ${API_KEY}`) {
49
+ return next(); // Authenticated
50
+ }
51
+
52
+ res.status(401).json({ error: 'Unauthorized: Invalid or missing API key' });
53
+ }
54
+ ]
55
+ });
56
+ ```
57
+
58
+ ### Example 2: Integration with third-party Identity Providers (JWT/OAuth)
59
+ You can use standard Express ecosystem libraries (like `express-oauth2-jwt-bearer` or custom JWT verification) to authenticate users remotely.
60
+
61
+ ```typescript
62
+ import { startHttpServer } from '@edicarlos.lds/businessmap-mcp';
63
+ import jwt from 'jsonwebtoken';
64
+
65
+ const JWT_SECRET = process.env.JWT_SECRET!;
66
+
67
+ await startHttpServer({
68
+ middlewares: [
69
+ (req, res, next) => {
70
+ if (req.path === '/health') return next();
71
+
72
+ const authHeader = req.headers['authorization'];
73
+ if (!authHeader?.startsWith('Bearer ')) {
74
+ return res.status(401).json({ error: 'Missing token' });
75
+ }
76
+
77
+ const token = authHeader.split(' ')[1];
78
+
79
+ try {
80
+ const decoded = jwt.verify(token, JWT_SECRET);
81
+ // Inject user info into request if needed
82
+ req.user = decoded;
83
+ next();
84
+ } catch (err) {
85
+ res.status(403).json({ error: 'Invalid or expired token' });
86
+ }
87
+ }
88
+ ]
89
+ });
90
+ ```
91
+
92
+ ---
93
+
94
+ ## šŸ›”ļø Adding Security and Rate-Limiting
95
+
96
+ You can pair authentication with popular security headers and rate-limiting packages from the npm ecosystem.
97
+
98
+ ```typescript
99
+ import { startHttpServer } from '@edicarlos.lds/businessmap-mcp';
100
+ import rateLimit from 'express-rate-limit';
101
+ import helmet from 'helmet';
102
+
103
+ // Limit clients to 100 requests per 15 minutes
104
+ const limiter = rateLimit({
105
+ windowMs: 15 * 60 * 1000,
106
+ max: 100,
107
+ message: { error: 'Too many requests, please try again later.' },
108
+ standardHeaders: true,
109
+ legacyHeaders: false,
110
+ });
111
+
112
+ await startHttpServer({
113
+ middlewares: [
114
+ helmet(), // Secure Express HTTP headers
115
+ limiter, // Limit rate
116
+ ],
117
+ });
118
+ ```
119
+
120
+ ---
121
+
122
+ ## āš™ļø Middleware Execution Order
123
+
124
+ Middlewares are executed sequentially in the order they are passed in the `middlewares` array.
125
+ 1. **JSON Parser & CORS** (Default built-in middlewares run first).
126
+ 2. **Custom Middlewares** (Your injected middlewares run next, allowing you to intercept and reject requests early).
127
+ 3. **Session Logging & Session Resolution** (Built-in MCP routing middleware matches the `/mcp` endpoints last).
128
+
129
+ ---
130
+
131
+ ## 🧪 Testing Your Middleware
132
+
133
+ You can test HTTP requests using `curl` or any API client (like Postman):
134
+
135
+ ```bash
136
+ # Testing request with header authorization
137
+ curl -X POST http://localhost:3000/mcp \
138
+ -H "Content-Type: application/json" \
139
+ -H "x-api-key: your-secret-api-key" \
140
+ -d '{"jsonrpc": "2.0", "method": "tools/list", "id": 1}'
141
+ ```
@@ -0,0 +1,146 @@
1
+ # Release Process
2
+
3
+ This document describes the automated release process for the BusinessMap MCP Server.
4
+
5
+ ## šŸš€ Automated Process
6
+
7
+ The release process has been fully automated and includes:
8
+
9
+ 1. **Version bump** (patch, minor, major)
10
+ 2. **Automatic release notes generation** based on commits
11
+ 3. **Git tag creation**
12
+ 4. **Push tag to GitHub**
13
+ 5. **GitHub release creation** with release notes
14
+ 6. **NPM publication**
15
+
16
+ ## šŸ“ How to Make a Release
17
+
18
+ ### 1. Preparation
19
+
20
+ Before making a release, ensure that:
21
+
22
+ - [ ] All changes are committed
23
+ - [ ] You are authenticated to NPM: `npm whoami` or make logging via `npm login`
24
+ - [ ] You are authenticated to GitHub CLI: `gh auth status`
25
+ - [ ] Working directory is clean
26
+
27
+ ### 2. Release Notes Preview
28
+
29
+ To see how the release notes will look before publishing:
30
+
31
+ ```bash
32
+ npm run preview:release
33
+ # or for a specific version:
34
+ npm run preview:release 1.2.3
35
+ ```
36
+
37
+ ### 3. Publication
38
+
39
+ Execute the publish npm command:
40
+
41
+ ```bash
42
+ npm run publish:npm
43
+ ```
44
+
45
+ The script will:
46
+
47
+ 1. Verify authentications
48
+ 2. Build and test
49
+ 3. Show version options (patch/minor/major)
50
+ 4. Generate release notes preview
51
+ 5. Confirm publication
52
+ 6. Execute the entire process automatically
53
+
54
+ ## šŸ“‹ Release Notes Format
55
+
56
+ Release notes are automatically generated based on commits since the last tag and organized by category:
57
+
58
+ ### šŸš€ New Features
59
+
60
+ - Commits starting with `feat:`, `feature:` or `FEAT:`
61
+
62
+ ### šŸ› Bug Fixes
63
+
64
+ - Commits starting with `fix:` or `FIX:`
65
+
66
+ ### ā™»ļø Code Refactoring
67
+
68
+ - Commits starting with `refactor:` or `REFACTOR:`
69
+
70
+ ### šŸ“š Documentation
71
+
72
+ - Commits starting with `docs:`, `doc:` or `DOCS:`
73
+
74
+ ### šŸ”§ Other Changes
75
+
76
+ - All other commits
77
+
78
+ ## šŸ·ļø Commit Convention
79
+
80
+ To maximize release notes quality, it's recommended to use the following prefixes:
81
+
82
+ ```bash
83
+ feat: add new functionality
84
+ fix: fix bug
85
+ docs: update documentation
86
+ refactor: refactor code
87
+ test: add or update tests
88
+ chore: maintenance tasks
89
+ ```
90
+
91
+ ## šŸ”§ Available Scripts
92
+
93
+ - `npm run publish:npm` - Publish to NPM only
94
+ - `npm run publish:github` - Create GitHub release only
95
+ - `npm run preview:release` - Preview release notes
96
+ - `scripts/generate-release-notes.sh` - Generate release notes for specific version
97
+
98
+ ## šŸŽÆ Example of Generated Release Notes
99
+
100
+ ```markdown
101
+ ## What's Changed
102
+
103
+ ### šŸš€ New Features
104
+ - add user authentication support by @username
105
+ - implement card filtering by @username
106
+
107
+ ### šŸ› Bug Fixes
108
+ - fix memory leak in client by @username
109
+ - resolve API timeout issues by @username
110
+
111
+ ### šŸ“š Documentation
112
+ - update README with new examples by @username
113
+
114
+ **Full Changelog**: https://github.com/edicarloslds/businessmap-mcp/compare/v1.0.0...v1.1.0
115
+ ```
116
+
117
+ ## 🚨 Troubleshooting
118
+
119
+ ### NPM Authentication Error
120
+
121
+ ```bash
122
+ npm login
123
+ ```
124
+
125
+ ### GitHub Authentication Error
126
+
127
+ ```bash
128
+ gh auth login
129
+ ```
130
+
131
+ ### Working Directory not clean
132
+
133
+ ```bash
134
+ git status
135
+ git add .
136
+ git commit -m "prepare for release"
137
+ ```
138
+
139
+ ### Tag already exists
140
+
141
+ If something goes wrong during the process, you can remove the created tag:
142
+
143
+ ```bash
144
+ git tag -d v1.2.3
145
+ git push origin :refs/tags/v1.2.3
146
+ ```
package/docs/TOOLS.md ADDED
@@ -0,0 +1,281 @@
1
+ # Tools, Resources & Prompts Reference
2
+
3
+ Complete reference for all tools, resources, and prompts provided by the BusinessMap MCP Server.
4
+
5
+ ## Summary
6
+
7
+ | Category | Count |
8
+ | --------- | :---: |
9
+ | Tools | 56 |
10
+ | Resources | 5 |
11
+ | Prompts | 4 |
12
+
13
+ ---
14
+
15
+ ## Tools
16
+
17
+ ### Workspace Management (3 tools)
18
+
19
+ | Tool | Description | Read-Only Safe |
20
+ | :----------------- | :---------------------------------- | :------------: |
21
+ | `list_workspaces` | Get a list of all workspaces | āœ… |
22
+ | `get_workspace` | Get details of a specific workspace | āœ… |
23
+ | `create_workspace` | Create a new workspace | āŒ |
24
+
25
+ ---
26
+
27
+ ### Board Management (11 tools)
28
+
29
+ | Tool | Description | Read-Only Safe |
30
+ | :---------------------------- | :--------------------------------------------------------------------------------------------- | :------------: |
31
+ | `list_boards` | Get a list of boards with optional workspace filter | āœ… |
32
+ | `search_board` | Search for a board by ID or name, with fallback to list | āœ… |
33
+ | `get_columns` | Get all columns for a board | āœ… |
34
+ | `get_lanes` | Get all lanes/swimlanes for a board | āœ… |
35
+ | `get_lane` | Get details of a specific lane/swimlane | āœ… |
36
+ | `get_current_board_structure` | Get the complete structure of a board (workflows, columns, lanes, configs) | āœ… |
37
+ | `create_board` | Create a new board in a workspace | āŒ |
38
+ | `create_lane` | Create a new lane/swimlane in a board | āŒ |
39
+ | `create_column` | Create a new column (main or sub-column). Section: 1=Backlog, 2=Requested, 3=Progress, 4=Done | āŒ |
40
+ | `update_column` | Update the details of a specific column | āŒ |
41
+ | `delete_column` | Delete a column from a board | āŒ āš ļø |
42
+
43
+ ---
44
+
45
+ ### Card Management (36 tools)
46
+
47
+ #### Basic Operations
48
+
49
+ | Tool | Description | Read-Only Safe |
50
+ | :--------------- | :------------------------------------------- | :------------: |
51
+ | `list_cards` | Get cards from a board with optional filters | āœ… |
52
+ | `get_card` | Get detailed card information | āœ… |
53
+ | `get_card_size` | Get the size/points of a specific card | āœ… |
54
+ | `get_card_types` | Get all available card types | āœ… |
55
+ | `create_card` | Create a new card in a board | āŒ |
56
+ | `move_card` | Move a card to a different column or lane | āŒ |
57
+ | `update_card` | Update card properties | āŒ |
58
+ | `set_card_size` | Set the size/points of a specific card | āŒ |
59
+ | `delete_card` | Permanently delete a card (irreversible) | āŒ āš ļø |
60
+
61
+ #### Comments
62
+
63
+ | Tool | Description | Read-Only Safe |
64
+ | :------------------ | :------------------------------------- | :------------: |
65
+ | `get_card_comments` | Get all comments for a specific card | āœ… |
66
+ | `get_card_comment` | Get details of a specific comment | āœ… |
67
+ | `create_comment` | Add a new comment to a card | āŒ |
68
+ | `update_comment` | Update the text of an existing comment | āŒ |
69
+ | `delete_comment` | Delete a comment from a card | āŒ āš ļø |
70
+
71
+ #### Custom Fields
72
+
73
+ | Tool | Description | Read-Only Safe |
74
+ | :----------------------- | :---------------------------------------- | :------------: |
75
+ | `get_card_custom_fields` | Get all custom fields for a specific card | āœ… |
76
+
77
+ #### Outcomes & History
78
+
79
+ | Tool | Description | Read-Only Safe |
80
+ | :------------------ | :----------------------------------------- | :------------: |
81
+ | `get_card_outcomes` | Get all outcomes for a specific card | āœ… |
82
+ | `get_card_history` | Get the history of a specific card outcome | āœ… |
83
+
84
+ #### Relationships
85
+
86
+ | Tool | Description | Read-Only Safe |
87
+ | :---------------------- | :--------------------------------------- | :------------: |
88
+ | `get_card_linked_cards` | Get all linked cards for a specific card | āœ… |
89
+
90
+ #### Subtasks
91
+
92
+ | Tool | Description | Read-Only Safe |
93
+ | :-------------------- | :----------------------------------- | :------------: |
94
+ | `get_card_subtasks` | Get all subtasks for a specific card | āœ… |
95
+ | `get_card_subtask` | Get details of a specific subtask | āœ… |
96
+ | `create_card_subtask` | Create a new subtask for a card | āŒ |
97
+
98
+ #### Parent-Child Relationships
99
+
100
+ | Tool | Description | Read-Only Safe |
101
+ | :---------------------- | :----------------------------------------------------- | :------------: |
102
+ | `get_card_parents` | Get a list of parent cards for a specific card | āœ… |
103
+ | `get_card_parent` | Check if a card is a parent of a given card | āœ… |
104
+ | `get_card_parent_graph` | Get parent cards including their parents (full graph) | āœ… |
105
+ | `get_card_children` | Get a list of child cards of a specified parent card | āœ… |
106
+ | `add_card_parent` | Make a card a parent of a given card | āŒ |
107
+ | `remove_card_parent` | Remove the link between a child card and a parent card | āŒ |
108
+
109
+ #### Blocking
110
+
111
+ | Tool | Description | Read-Only Safe |
112
+ | :------------- | :------------------------------------------ | :------------: |
113
+ | `block_card` | Block a card and set a reason/comment | āŒ |
114
+ | `unblock_card` | Unblock a card by removing its block reason | āŒ |
115
+
116
+ #### Tags
117
+
118
+ | Tool | Description | Read-Only Safe |
119
+ | :--------------------- | :-------------------------------- | :------------: |
120
+ | `create_tag` | Create a new tag in the workspace | āŒ |
121
+ | `add_tag_to_card` | Add an existing tag to a card | āŒ |
122
+ | `remove_tag_from_card` | Remove a tag from a card | āŒ |
123
+
124
+ #### Stickers
125
+
126
+ | Tool | Description | Read-Only Safe |
127
+ | :------------------------- | :----------------------------------------------------------------- | :------------: |
128
+ | `add_sticker_to_card` | Add a sticker to a card | āŒ |
129
+ | `remove_sticker_from_card` | Remove a sticker from a card using the sticker-card association ID | āŒ |
130
+
131
+ #### Predecessors
132
+
133
+ | Tool | Description | Read-Only Safe |
134
+ | :------------------- | :------------------------------------------------------------------------- | :------------: |
135
+ | `add_predecessor` | Establish or update a predecessor-successor relationship between two cards | āŒ |
136
+ | `remove_predecessor` | Remove the predecessor-successor relationship between two cards | āŒ |
137
+
138
+ ---
139
+
140
+ ### Custom Field Management (1 tool)
141
+
142
+ | Tool | Description | Read-Only Safe |
143
+ | :----------------- | :------------------------------------------- | :------------: |
144
+ | `get_custom_field` | Get details of a specific custom field by ID | āœ… |
145
+
146
+ ---
147
+
148
+ ### Workflow & Cycle Time Analysis (2 tools)
149
+
150
+ | Tool | Description | Read-Only Safe |
151
+ | :------------------------------------------ | :------------------------------------------ | :------------: |
152
+ | `get_workflow_cycle_time_columns` | Get workflow's cycle time columns | āœ… |
153
+ | `get_workflow_effective_cycle_time_columns` | Get workflow's effective cycle time columns | āœ… |
154
+
155
+ ---
156
+
157
+ ### User Management (4 tools)
158
+
159
+ | Tool | Description | Read-Only Safe |
160
+ | :----------------- | :------------------------------------- | :------------: |
161
+ | `list_users` | Get a list of all users | āœ… |
162
+ | `get_user` | Get details of a specific user | āœ… |
163
+ | `get_current_user` | Get details of the current logged user | āœ… |
164
+ | `invite_user` | Add and invite a new user by email | āŒ |
165
+
166
+ ---
167
+
168
+ ### System (2 tools)
169
+
170
+ | Tool | Description | Read-Only Safe |
171
+ | :------------- | :---------------------------------------- | :------------: |
172
+ | `health_check` | Check the connection to BusinessMap API | āœ… |
173
+ | `get_api_info` | Get information about the BusinessMap API | āœ… |
174
+
175
+ ---
176
+
177
+ ## Resources
178
+
179
+ MCP resources provide structured data access via URI. Clients can read resources directly without invoking tools.
180
+
181
+ | URI | Name | Description | Listable |
182
+ | :-------------------------------------- | :----------- | :---------------------------------- | :------: |
183
+ | `businessmap://workspaces` | `workspaces` | List all workspaces | āœ… |
184
+ | `businessmap://boards` | `boards` | List all boards | āœ… |
185
+ | `businessmap://boards/{board_id}` | `board` | Get details of a specific board | āŒ |
186
+ | `businessmap://boards/{board_id}/cards` | `cards` | List all cards for a specific board | āœ… |
187
+ | `businessmap://cards/{card_id}` | `card` | Get details of a specific card | āŒ |
188
+
189
+ ---
190
+
191
+ ## Prompts
192
+
193
+ MCP prompts provide guided, multi-step workflows for common AI-assisted tasks.
194
+
195
+ ### `analyze-board-performance`
196
+
197
+ **Title:** Analyze Board Performance
198
+
199
+ Analyze a board's performance: flow efficiency, bottlenecks, cycle time, and workload distribution across columns and lanes.
200
+
201
+ **Arguments:**
202
+
203
+ - `board_id` (required) — The board ID to analyze
204
+
205
+ **Workflow:**
206
+
207
+ 1. Uses `get_current_board_structure` to retrieve the full board structure
208
+ 2. Uses `list_cards` to retrieve all active cards
209
+ 3. Uses `get_workflow_cycle_time_columns` for each workflow
210
+ 4. Delivers a structured analysis covering flow efficiency, cycle time, workload distribution, and actionable recommendations
211
+
212
+ ---
213
+
214
+ ### `generate-board-report`
215
+
216
+ **Title:** Generate Board Report
217
+
218
+ Generate a comprehensive status report for a board, including cards summary, progress, and highlights.
219
+
220
+ **Arguments:**
221
+
222
+ - `board_id` (required) — The board ID to report on
223
+
224
+ **Workflow:**
225
+
226
+ 1. Uses `get_current_board_structure` to get the board structure
227
+ 2. Uses `list_cards` to get all cards
228
+ 3. Uses `get_card` for detailed info on a sample of cards
229
+ 4. Generates a structured report with: Executive Summary, Column Breakdown, Recently Updated Cards, Risks & Blockers, and Next Steps
230
+
231
+ ---
232
+
233
+ ### `create-card-from-description`
234
+
235
+ **Title:** Create Card from Description
236
+
237
+ Guide the creation of a well-structured card from a natural language description.
238
+
239
+ **Arguments:**
240
+
241
+ - `description` (required) — Natural language description of what the card should be
242
+ - `board_id` (required) — The board ID where the card should be created
243
+
244
+ **Workflow:**
245
+
246
+ 1. Uses `get_current_board_structure` to understand available columns, lanes, and workflows
247
+ 2. Uses `get_card_types` to list available card types
248
+ 3. Determines the best card title, description, type, target column, lane, and size/priority
249
+ 4. Uses `create_card` to create the card and confirms creation with ID and summary
250
+
251
+ ---
252
+
253
+ ### `workspace-status-overview`
254
+
255
+ **Title:** Workspace Status Overview
256
+
257
+ Generate a high-level status overview of a workspace, including all boards and their key metrics.
258
+
259
+ **Arguments:**
260
+
261
+ - `workspace_id` (required) — The workspace ID to generate an overview for
262
+
263
+ **Workflow:**
264
+
265
+ 1. Uses `get_workspace` to get workspace details
266
+ 2. Uses `list_boards` with `workspace_id` filter to list all boards
267
+ 3. Uses `list_cards` for each board to get active card counts
268
+ 4. Uses `get_current_board_structure` for up to 3 boards
269
+ 5. Delivers a structured overview with: Workspace Summary, Board Summaries, Highlights, and Recommendations
270
+
271
+ ---
272
+
273
+ ## Read-Only Mode
274
+
275
+ When `BUSINESSMAP_READ_ONLY_MODE=true`, only tools marked āœ… in the "Read-Only Safe" column are registered. Write operations (āŒ) are not available. This is useful for:
276
+
277
+ - Safe data exploration without risk of modifications
278
+ - Granting read-only access to AI assistants
279
+ - Auditing and reporting use cases
280
+
281
+ > Note: All 5 resources and all 4 prompts are available regardless of read-only mode setting.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@edicarlos.lds/businessmap-mcp",
3
- "version": "2.1.1",
3
+ "version": "2.2.0",
4
4
  "description": "Model Context Protocol server for BusinessMap (Kanbanize) integration",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -9,6 +9,7 @@
9
9
  },
10
10
  "files": [
11
11
  "dist",
12
+ "docs",
12
13
  "README.md",
13
14
  "LICENSE"
14
15
  ],