@specforge/mcp 1.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.
@@ -0,0 +1,71 @@
1
+ /**
2
+ * MCP Configuration Module
3
+ *
4
+ * Loads and validates configuration from environment variables for
5
+ * the SpecForge MCP server.
6
+ */
7
+ /**
8
+ * MCP Server configuration
9
+ */
10
+ export interface McpConfig {
11
+ /** API key for authentication (format: sf_live_*) */
12
+ apiKey: string;
13
+ /** API Gateway URL for the SpecForge backend */
14
+ apiUrl: string;
15
+ /** Enable debug logging */
16
+ debug: boolean;
17
+ }
18
+ /**
19
+ * Environment variable names
20
+ */
21
+ export declare const ENV_VARS: {
22
+ readonly API_KEY: "SPECFORGE_API_KEY";
23
+ readonly API_URL: "SPECFORGE_API_URL";
24
+ readonly DEBUG: "SPECFORGE_DEBUG";
25
+ };
26
+ /**
27
+ * Load configuration from environment variables
28
+ *
29
+ * @throws {Error} If required environment variables are missing
30
+ * @returns {McpConfig} Loaded configuration
31
+ *
32
+ * @example
33
+ * ```typescript
34
+ * const config = loadConfig();
35
+ * console.log(config.apiUrl);
36
+ * ```
37
+ */
38
+ export declare function loadConfig(): McpConfig;
39
+ /**
40
+ * Validate configuration values
41
+ *
42
+ * @param config - Configuration to validate
43
+ * @throws {Error} If configuration is invalid
44
+ *
45
+ * @example
46
+ * ```typescript
47
+ * const config = loadConfig();
48
+ * validateConfig(config); // Throws if invalid
49
+ * ```
50
+ */
51
+ export declare function validateConfig(config: McpConfig): void;
52
+ /**
53
+ * Load and validate configuration in one step
54
+ *
55
+ * @throws {Error} If configuration is missing or invalid
56
+ * @returns {McpConfig} Validated configuration
57
+ *
58
+ * @example
59
+ * ```typescript
60
+ * const config = getConfig();
61
+ * // Configuration is guaranteed to be valid
62
+ * ```
63
+ */
64
+ export declare function getConfig(): McpConfig;
65
+ /**
66
+ * Check if configuration is available without throwing
67
+ *
68
+ * @returns {boolean} True if all required environment variables are set
69
+ */
70
+ export declare function isConfigured(): boolean;
71
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/config/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,qDAAqD;IACrD,MAAM,EAAE,MAAM,CAAC;IACf,gDAAgD;IAChD,MAAM,EAAE,MAAM,CAAC;IACf,2BAA2B;IAC3B,KAAK,EAAE,OAAO,CAAC;CAChB;AAED;;GAEG;AACH,eAAO,MAAM,QAAQ;;;;CAIX,CAAC;AAYX;;;;;;;;;;;GAWG;AACH,wBAAgB,UAAU,IAAI,SAAS,CAqBtC;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAuCtD;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,SAAS,IAAI,SAAS,CAIrC;AAED;;;;GAIG;AACH,wBAAgB,YAAY,IAAI,OAAO,CAEtC"}
@@ -0,0 +1,120 @@
1
+ /**
2
+ * MCP Configuration Module
3
+ *
4
+ * Loads and validates configuration from environment variables for
5
+ * the SpecForge MCP server.
6
+ */
7
+ /**
8
+ * Environment variable names
9
+ */
10
+ export const ENV_VARS = {
11
+ API_KEY: 'SPECFORGE_API_KEY',
12
+ API_URL: 'SPECFORGE_API_URL', // Optional - for self-hosted deployments
13
+ DEBUG: 'SPECFORGE_DEBUG',
14
+ };
15
+ /**
16
+ * Default API URL for SpecForge production
17
+ */
18
+ const DEFAULT_API_URL = 'https://mcp.specforge.com.br';
19
+ /**
20
+ * API key prefix for validation
21
+ */
22
+ const API_KEY_PREFIX = 'sf_live_';
23
+ /**
24
+ * Load configuration from environment variables
25
+ *
26
+ * @throws {Error} If required environment variables are missing
27
+ * @returns {McpConfig} Loaded configuration
28
+ *
29
+ * @example
30
+ * ```typescript
31
+ * const config = loadConfig();
32
+ * console.log(config.apiUrl);
33
+ * ```
34
+ */
35
+ export function loadConfig() {
36
+ const apiKey = process.env[ENV_VARS.API_KEY];
37
+ const apiUrl = process.env[ENV_VARS.API_URL] || DEFAULT_API_URL;
38
+ const debug = process.env[ENV_VARS.DEBUG] === 'true';
39
+ if (!apiKey) {
40
+ throw new Error(`${ENV_VARS.API_KEY} environment variable is required.\n` +
41
+ 'Get your API key from the SpecForge webapp:\n' +
42
+ ' 1. Go to Settings > API Keys\n' +
43
+ ' 2. Create a new API key\n' +
44
+ ' 3. Copy the key (starts with sf_live_)\n' +
45
+ ` 4. Set: export ${ENV_VARS.API_KEY}="your_key"`);
46
+ }
47
+ return {
48
+ apiKey,
49
+ apiUrl,
50
+ debug,
51
+ };
52
+ }
53
+ /**
54
+ * Validate configuration values
55
+ *
56
+ * @param config - Configuration to validate
57
+ * @throws {Error} If configuration is invalid
58
+ *
59
+ * @example
60
+ * ```typescript
61
+ * const config = loadConfig();
62
+ * validateConfig(config); // Throws if invalid
63
+ * ```
64
+ */
65
+ export function validateConfig(config) {
66
+ // Validate API key format
67
+ if (!config.apiKey.startsWith(API_KEY_PREFIX)) {
68
+ throw new Error(`Invalid API key format.\n` +
69
+ ` Expected: Key starting with "${API_KEY_PREFIX}"\n` +
70
+ ` Got: "${config.apiKey.substring(0, 10)}..."\n` +
71
+ '\nMake sure you copied the full API key from the SpecForge webapp.');
72
+ }
73
+ // Validate API key minimum length (prefix + at least 20 chars)
74
+ if (config.apiKey.length < API_KEY_PREFIX.length + 20) {
75
+ throw new Error(`Invalid API key length.\n` +
76
+ ' API keys should be at least 28 characters long.\n' +
77
+ ' Make sure you copied the full key.');
78
+ }
79
+ // Validate API URL format
80
+ try {
81
+ const url = new URL(config.apiUrl);
82
+ // Must be HTTPS in production
83
+ if (url.protocol !== 'https:' && !config.debug) {
84
+ console.warn(`Warning: API URL is not using HTTPS: ${config.apiUrl}\n` +
85
+ ' This is allowed in debug mode but not recommended for production.');
86
+ }
87
+ }
88
+ catch {
89
+ throw new Error(`Invalid API URL format.\n` +
90
+ ` Expected: Valid URL (e.g., https://api.example.com/prod)\n` +
91
+ ` Got: "${config.apiUrl}"\n` +
92
+ '\nMake sure you copied the full URL including the protocol.');
93
+ }
94
+ }
95
+ /**
96
+ * Load and validate configuration in one step
97
+ *
98
+ * @throws {Error} If configuration is missing or invalid
99
+ * @returns {McpConfig} Validated configuration
100
+ *
101
+ * @example
102
+ * ```typescript
103
+ * const config = getConfig();
104
+ * // Configuration is guaranteed to be valid
105
+ * ```
106
+ */
107
+ export function getConfig() {
108
+ const config = loadConfig();
109
+ validateConfig(config);
110
+ return config;
111
+ }
112
+ /**
113
+ * Check if configuration is available without throwing
114
+ *
115
+ * @returns {boolean} True if all required environment variables are set
116
+ */
117
+ export function isConfigured() {
118
+ return !!process.env[ENV_VARS.API_KEY];
119
+ }
120
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/config/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAcH;;GAEG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG;IACtB,OAAO,EAAE,mBAAmB;IAC5B,OAAO,EAAE,mBAAmB,EAAE,yCAAyC;IACvE,KAAK,EAAE,iBAAiB;CAChB,CAAC;AAEX;;GAEG;AACH,MAAM,eAAe,GAAG,8BAA8B,CAAC;AAEvD;;GAEG;AACH,MAAM,cAAc,GAAG,UAAU,CAAC;AAElC;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,UAAU;IACxB,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;IAC7C,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,eAAe,CAAC;IAChE,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,KAAK,MAAM,CAAC;IAErD,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CACb,GAAG,QAAQ,CAAC,OAAO,sCAAsC;YACvD,+CAA+C;YAC/C,kCAAkC;YAClC,6BAA6B;YAC7B,4CAA4C;YAC5C,oBAAoB,QAAQ,CAAC,OAAO,aAAa,CACpD,CAAC;IACJ,CAAC;IAED,OAAO;QACL,MAAM;QACN,MAAM;QACN,KAAK;KACN,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,cAAc,CAAC,MAAiB;IAC9C,0BAA0B;IAC1B,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,cAAc,CAAC,EAAE,CAAC;QAC9C,MAAM,IAAI,KAAK,CACb,2BAA2B;YACzB,kCAAkC,cAAc,KAAK;YACrD,WAAW,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ;YACjD,oEAAoE,CACvE,CAAC;IACJ,CAAC;IAED,+DAA+D;IAC/D,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,cAAc,CAAC,MAAM,GAAG,EAAE,EAAE,CAAC;QACtD,MAAM,IAAI,KAAK,CACb,2BAA2B;YACzB,qDAAqD;YACrD,sCAAsC,CACzC,CAAC;IACJ,CAAC;IAED,0BAA0B;IAC1B,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QAEnC,8BAA8B;QAC9B,IAAI,GAAG,CAAC,QAAQ,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;YAC/C,OAAO,CAAC,IAAI,CACV,wCAAwC,MAAM,CAAC,MAAM,IAAI;gBACvD,qEAAqE,CACxE,CAAC;QACJ,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,KAAK,CACb,2BAA2B;YACzB,8DAA8D;YAC9D,WAAW,MAAM,CAAC,MAAM,KAAK;YAC7B,6DAA6D,CAChE,CAAC;IACJ,CAAC;AACH,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,SAAS;IACvB,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;IAC5B,cAAc,CAAC,MAAM,CAAC,CAAC;IACvB,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,YAAY;IAC1B,OAAO,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;AACzC,CAAC"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * SpecForge MCP Server
3
+ *
4
+ * This is the main entry point for the SpecForge MCP (Model Context Protocol) server.
5
+ * It provides tools for AI agents to interact with SpecForge projects, specifications,
6
+ * epics, and tickets.
7
+ *
8
+ * @module @specforge/mcp
9
+ */
10
+ export { McpConfig, loadConfig, validateConfig, getConfig, isConfigured, ENV_VARS } from './config/index.js';
11
+ export { ApiClient, ApiResponse, ApiKeyValidationResult, ApiRequestOptions } from './client/api-client.js';
12
+ export { createServer, startServer } from './server.js';
13
+ export { getTools, handleToolCall, handleToolCallSafe, Tool } from './tools/index.js';
14
+ export { ValidationError, ApiError, validateToolArgs, formatMCPError, transformError, MCPErrorResponse, } from './validation/index.js';
15
+ export * from './types/index.js';
16
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,cAAc,EAAE,SAAS,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAG7G,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,sBAAsB,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAG3G,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAGxD,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,kBAAkB,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAGtF,OAAO,EACL,eAAe,EACf,QAAQ,EACR,gBAAgB,EAChB,cAAc,EACd,cAAc,EACd,gBAAgB,GACjB,MAAM,uBAAuB,CAAC;AAG/B,cAAc,kBAAkB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,60 @@
1
+ /**
2
+ * SpecForge MCP Server
3
+ *
4
+ * This is the main entry point for the SpecForge MCP (Model Context Protocol) server.
5
+ * It provides tools for AI agents to interact with SpecForge projects, specifications,
6
+ * epics, and tickets.
7
+ *
8
+ * @module @specforge/mcp
9
+ */
10
+ // Export configuration
11
+ export { loadConfig, validateConfig, getConfig, isConfigured, ENV_VARS } from './config/index.js';
12
+ // Export API client
13
+ export { ApiClient } from './client/api-client.js';
14
+ // Export server
15
+ export { createServer, startServer } from './server.js';
16
+ // Export tools
17
+ export { getTools, handleToolCall, handleToolCallSafe } from './tools/index.js';
18
+ // Export validation
19
+ export { ValidationError, ApiError, validateToolArgs, formatMCPError, transformError, } from './validation/index.js';
20
+ // Export types
21
+ export * from './types/index.js';
22
+ // Main entry point
23
+ async function main() {
24
+ // Import dynamically to avoid circular dependency issues
25
+ const { loadConfig, validateConfig } = await import('./config/index.js');
26
+ const { createServer, startServer } = await import('./server.js');
27
+ try {
28
+ const config = loadConfig();
29
+ validateConfig(config);
30
+ if (config.debug) {
31
+ console.error('[DEBUG] Configuration loaded:', {
32
+ apiUrl: config.apiUrl,
33
+ apiKey: config.apiKey.substring(0, 15) + '...',
34
+ debug: config.debug,
35
+ });
36
+ }
37
+ console.error('[INFO] Starting SpecForge MCP server...');
38
+ const server = await createServer(config);
39
+ await startServer(server);
40
+ if (config.debug) {
41
+ console.error('[DEBUG] MCP server started and connected');
42
+ }
43
+ }
44
+ catch (error) {
45
+ console.error('[ERROR] Failed to start MCP server:', error);
46
+ process.exit(1);
47
+ }
48
+ }
49
+ // Run if executed directly (not when imported as a library)
50
+ // In ESM, we check if this is the entry point by comparing with process.argv
51
+ const isDirectRun = process.argv[1]?.endsWith('index.js') ||
52
+ process.argv[1]?.endsWith('index.ts') ||
53
+ process.argv[1]?.includes('@specforge/mcp');
54
+ if (isDirectRun && !process.env.VITEST) {
55
+ main().catch((error) => {
56
+ console.error('[ERROR] Unhandled error:', error);
57
+ process.exit(1);
58
+ });
59
+ }
60
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,uBAAuB;AACvB,OAAO,EAAa,UAAU,EAAE,cAAc,EAAE,SAAS,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAE7G,oBAAoB;AACpB,OAAO,EAAE,SAAS,EAA0D,MAAM,wBAAwB,CAAC;AAE3G,gBAAgB;AAChB,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAExD,eAAe;AACf,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,kBAAkB,EAAQ,MAAM,kBAAkB,CAAC;AAEtF,oBAAoB;AACpB,OAAO,EACL,eAAe,EACf,QAAQ,EACR,gBAAgB,EAChB,cAAc,EACd,cAAc,GAEf,MAAM,uBAAuB,CAAC;AAE/B,eAAe;AACf,cAAc,kBAAkB,CAAC;AAEjC,mBAAmB;AACnB,KAAK,UAAU,IAAI;IACjB,yDAAyD;IACzD,MAAM,EAAE,UAAU,EAAE,cAAc,EAAE,GAAG,MAAM,MAAM,CAAC,mBAAmB,CAAC,CAAC;IACzE,MAAM,EAAE,YAAY,EAAE,WAAW,EAAE,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,CAAC;IAElE,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;QAC5B,cAAc,CAAC,MAAM,CAAC,CAAC;QAEvB,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;YACjB,OAAO,CAAC,KAAK,CAAC,+BAA+B,EAAE;gBAC7C,MAAM,EAAE,MAAM,CAAC,MAAM;gBACrB,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,KAAK;gBAC9C,KAAK,EAAE,MAAM,CAAC,KAAK;aACpB,CAAC,CAAC;QACL,CAAC;QAED,OAAO,CAAC,KAAK,CAAC,yCAAyC,CAAC,CAAC;QAEzD,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,MAAM,CAAC,CAAC;QAC1C,MAAM,WAAW,CAAC,MAAM,CAAC,CAAC;QAE1B,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;YACjB,OAAO,CAAC,KAAK,CAAC,0CAA0C,CAAC,CAAC;QAC5D,CAAC;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,qCAAqC,EAAE,KAAK,CAAC,CAAC;QAC5D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC;AAED,4DAA4D;AAC5D,6EAA6E;AAC7E,MAAM,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,UAAU,CAAC;IACrC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,UAAU,CAAC;IACrC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,gBAAgB,CAAC,CAAC;AAEhE,IAAI,WAAW,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC;IACvC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;QACrB,OAAO,CAAC,KAAK,CAAC,0BAA0B,EAAE,KAAK,CAAC,CAAC;QACjD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * SpecForge MCP Server
3
+ *
4
+ * MCP (Model Context Protocol) server implementation using stdio transport.
5
+ * Provides tools for AI agents to interact with SpecForge projects.
6
+ */
7
+ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
8
+ import { McpConfig } from './config/index.js';
9
+ /**
10
+ * Create and configure the MCP server
11
+ *
12
+ * @param config - Configuration for the server
13
+ * @returns Configured MCP Server instance
14
+ */
15
+ export declare function createServer(config: McpConfig): Promise<Server>;
16
+ /**
17
+ * Start the MCP server with stdio transport
18
+ *
19
+ * @param server - The MCP server instance
20
+ */
21
+ export declare function startServer(server: Server): Promise<void>;
22
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AAOnE,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAQ9C;;;;;GAKG;AACH,wBAAsB,YAAY,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC,CAkErE;AAED;;;;GAIG;AACH,wBAAsB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA0B/D"}
package/dist/server.js ADDED
@@ -0,0 +1,100 @@
1
+ /**
2
+ * SpecForge MCP Server
3
+ *
4
+ * MCP (Model Context Protocol) server implementation using stdio transport.
5
+ * Provides tools for AI agents to interact with SpecForge projects.
6
+ */
7
+ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
8
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
9
+ import { CallToolRequestSchema, ListToolsRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
10
+ import { ApiClient } from './client/api-client.js';
11
+ import { getTools, handleToolCall } from './tools/index.js';
12
+ /**
13
+ * Package version - should match package.json
14
+ */
15
+ const VERSION = '1.0.0';
16
+ /**
17
+ * Create and configure the MCP server
18
+ *
19
+ * @param config - Configuration for the server
20
+ * @returns Configured MCP Server instance
21
+ */
22
+ export async function createServer(config) {
23
+ const apiClient = new ApiClient(config);
24
+ const server = new Server({
25
+ name: 'specforge-mcp',
26
+ version: VERSION,
27
+ }, {
28
+ capabilities: {
29
+ tools: {},
30
+ },
31
+ });
32
+ // Handle ListTools requests - return available tools
33
+ server.setRequestHandler(ListToolsRequestSchema, async () => {
34
+ if (config.debug) {
35
+ console.error('[DEBUG] ListTools request received');
36
+ }
37
+ const tools = getTools();
38
+ if (config.debug) {
39
+ console.error(`[DEBUG] Returning ${tools.length} tools`);
40
+ }
41
+ return { tools };
42
+ });
43
+ // Handle CallTool requests - execute the requested tool
44
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
45
+ const { name, arguments: args } = request.params;
46
+ if (config.debug) {
47
+ console.error('[DEBUG] CallTool request:', {
48
+ name,
49
+ args: JSON.stringify(args),
50
+ });
51
+ }
52
+ try {
53
+ const result = await handleToolCall(apiClient, name, args || {}, config.debug);
54
+ // Format result as text content
55
+ const text = typeof result === 'string' ? result : JSON.stringify(result, null, 2);
56
+ return {
57
+ content: [{ type: 'text', text }],
58
+ };
59
+ }
60
+ catch (error) {
61
+ const message = error instanceof Error ? error.message : String(error);
62
+ if (config.debug) {
63
+ console.error(`[DEBUG] Tool ${name} failed:`, message);
64
+ }
65
+ return {
66
+ content: [{ type: 'text', text: `Error: ${message}` }],
67
+ isError: true,
68
+ };
69
+ }
70
+ });
71
+ return server;
72
+ }
73
+ /**
74
+ * Start the MCP server with stdio transport
75
+ *
76
+ * @param server - The MCP server instance
77
+ */
78
+ export async function startServer(server) {
79
+ const transport = new StdioServerTransport();
80
+ // Handle graceful shutdown
81
+ const shutdown = async () => {
82
+ console.error('[INFO] Shutting down MCP server...');
83
+ await server.close();
84
+ process.exit(0);
85
+ };
86
+ process.on('SIGINT', shutdown);
87
+ process.on('SIGTERM', shutdown);
88
+ // Handle uncaught errors
89
+ process.on('uncaughtException', (error) => {
90
+ console.error('[ERROR] Uncaught exception:', error);
91
+ process.exit(1);
92
+ });
93
+ process.on('unhandledRejection', (reason) => {
94
+ console.error('[ERROR] Unhandled rejection:', reason);
95
+ process.exit(1);
96
+ });
97
+ // Connect to transport
98
+ await server.connect(transport);
99
+ }
100
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,79 @@
1
+ /**
2
+ * MCP Tools Registry
3
+ *
4
+ * This module defines and exports all available MCP tools.
5
+ * All operations from Epics 3-10 are registered here with proper JSON Schema definitions.
6
+ *
7
+ * Tool categories:
8
+ * - Core Operations: Project, Specification, Epic, Ticket, Dependency
9
+ * - Context & AI: Implementation context, actionable tickets, critical path
10
+ * - Workflow: Work sessions, progress reporting
11
+ * - Testing: Test results, validation
12
+ * - Discovery: Report and resolve discoveries
13
+ * - Status: Status reports, summaries, analytics
14
+ * - Search: Search, find by file/tag, find related
15
+ * - Git: Link commits and PRs, get linked items
16
+ */
17
+ import { ApiClient } from '../client/api-client.js';
18
+ import { MCPErrorResponse } from '../validation/index.js';
19
+ /**
20
+ * Tool definition matching MCP protocol schema
21
+ */
22
+ export interface Tool {
23
+ name: string;
24
+ description: string;
25
+ inputSchema: {
26
+ type: 'object';
27
+ properties: Record<string, unknown>;
28
+ required?: string[];
29
+ };
30
+ }
31
+ /**
32
+ * Get list of all available tools
33
+ *
34
+ * This returns the tool definitions that will be sent to the AI client
35
+ * in response to ListTools requests.
36
+ *
37
+ * @returns Array of tool definitions
38
+ */
39
+ export declare function getTools(): Tool[];
40
+ /**
41
+ * Tool handler type - processes arguments and returns a result
42
+ */
43
+ type ToolHandler = (apiClient: ApiClient, args: Record<string, unknown>) => Promise<unknown>;
44
+ /**
45
+ * Create tool handlers that call the API with proper request formatting
46
+ *
47
+ * Each handler:
48
+ * - Validates required arguments
49
+ * - Formats the request for the API
50
+ * - Parses and transforms the response
51
+ * - Handles errors appropriately
52
+ *
53
+ * @param apiClient - The API client to use for making requests
54
+ * @returns Record of tool handlers keyed by tool name
55
+ */
56
+ export declare function createToolHandlers(apiClient: ApiClient): Record<string, ToolHandler>;
57
+ /**
58
+ * Handle a tool call by routing to the appropriate handler
59
+ *
60
+ * @param apiClient - The API client to use for making requests
61
+ * @param toolName - Name of the tool being called
62
+ * @param args - Arguments passed to the tool
63
+ * @param debug - Whether to enable debug logging
64
+ * @returns Promise resolving to the tool result
65
+ */
66
+ export declare function handleToolCall(apiClient: ApiClient, toolName: string, args: Record<string, unknown>, debug?: boolean): Promise<unknown>;
67
+ /**
68
+ * Handle a tool call and return MCP-formatted response
69
+ * This wraps handleToolCall with proper error formatting for MCP protocol
70
+ *
71
+ * @param apiClient - The API client to use for making requests
72
+ * @param toolName - Name of the tool being called
73
+ * @param args - Arguments passed to the tool
74
+ * @param debug - Whether to enable debug logging
75
+ * @returns Promise resolving to either the result or an MCP error response
76
+ */
77
+ export declare function handleToolCallSafe(apiClient: ApiClient, toolName: string, args: Record<string, unknown>, debug?: boolean): Promise<unknown | MCPErrorResponse>;
78
+ export { ValidationError, ApiError, validateToolArgs, formatMCPError, transformError, type MCPErrorResponse, } from '../validation/index.js';
79
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AACpD,OAAO,EAML,gBAAgB,EACjB,MAAM,wBAAwB,CAAC;AAEhC;;GAEG;AACH,MAAM,WAAW,IAAI;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE;QACX,IAAI,EAAE,QAAQ,CAAC;QACf,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QACpC,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;KACrB,CAAC;CACH;AAED;;;;;;;GAOG;AACH,wBAAgB,QAAQ,IAAI,IAAI,EAAE,CAuhCjC;AAED;;GAEG;AACH,KAAK,WAAW,GAAG,CACjB,SAAS,EAAE,SAAS,EACpB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAC1B,OAAO,CAAC,OAAO,CAAC,CAAC;AA6EtB;;;;;;;;;;;GAWG;AACH,wBAAgB,kBAAkB,CAChC,SAAS,EAAE,SAAS,GACnB,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAka7B;AAqCD;;;;;;;;GAQG;AACH,wBAAsB,cAAc,CAClC,SAAS,EAAE,SAAS,EACpB,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,KAAK,GAAE,OAAe,GACrB,OAAO,CAAC,OAAO,CAAC,CA4DlB;AAED;;;;;;;;;GASG;AACH,wBAAsB,kBAAkB,CACtC,SAAS,EAAE,SAAS,EACpB,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,KAAK,GAAE,OAAe,GACrB,OAAO,CAAC,OAAO,GAAG,gBAAgB,CAAC,CAOrC;AAGD,OAAO,EACL,eAAe,EACf,QAAQ,EACR,gBAAgB,EAChB,cAAc,EACd,cAAc,EACd,KAAK,gBAAgB,GACtB,MAAM,wBAAwB,CAAC"}