Skip to content

Commit 4e26d20

Browse files
committed
update readme
1 parent aa82d66 commit 4e26d20

File tree

3 files changed

+58
-179
lines changed

3 files changed

+58
-179
lines changed

README.md

Lines changed: 10 additions & 164 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,23 @@
11
# FAIM MCP Server
22

3-
A production-ready Model Context Protocol (MCP) server that integrates the FAIM time series forecasting SDK with any MCP-compatible AI assistant, enabling AI-powered forecasting capabilities.
3+
A Model Context Protocol (MCP) server that integrates the FAIM time series forecasting SDK with any MCP-compatible AI assistant, enabling AI-powered forecasting capabilities.
44

5-
**Now powered by the official `@modelcontextprotocol/sdk`** - No manual protocol implementation, full type safety, and complete MCP specification compliance.
65

76
## Overview
87

9-
This MCP server exposes two forecasting models from the FAIM API:
10-
- **Chronos2**: General-purpose time series forecasting model
11-
- **TiRex**: Alternative forecasting model with different characteristics
12-
13-
### Official SDK Implementation
14-
15-
This server uses the **official `@modelcontextprotocol/sdk`** package from Anthropic. Key benefits:
16-
17-
- **Zero Manual Protocol Handling**: The SDK completely handles JSON-RPC 2.0 protocol, message formatting, and transport
18-
- **Production-Ready**: Maintained by Anthropic, used in production Claude integrations
19-
- **Type-Safe**: Full TypeScript support with complete type definitions
20-
- **Forward Compatible**: Automatic support for future MCP protocol updates
21-
- **Minimal Code**: ~250 lines of application code vs ~400 lines of custom protocol handling
22-
- **Built-in Validation**: Schema validation and error handling provided by SDK
8+
This MCP server currently exposes two foundation time-series models from the FAIM API for zero-shot forecasting:
9+
- **Chronos2**
10+
- **TiRex**
2311

2412
### Key Features
2513

2614
**Two MCP Tools**:
2715
- `list_models`: Returns available forecasting models and capabilities
2816
- `forecast`: Performs point and probabilistic time series forecasting
2917

30-
**Production-Ready**:
31-
- Comprehensive error handling with helpful error messages
32-
- Input validation with detailed feedback
33-
- JSON-RPC stdio communication (MCP protocol)
34-
- Full TypeScript type safety
35-
- Extensive test coverage
36-
3718
**Flexible Input Formats**:
3819
- 1D arrays: Single univariate time series
39-
- 2D arrays: Multivariate or batch time series
40-
- 3D arrays: Explicit batch/sequence/feature format
20+
- 3D arrays: batch/sequence/feature format
4121

4222
**Probabilistic Forecasting**:
4323
- Point forecasts (single value predictions)
@@ -51,15 +31,15 @@ This server uses the **official `@modelcontextprotocol/sdk`** package from Anthr
5131

5232
- Node.js 20+
5333
- npm 10+
54-
- FAIM API key (set as `FAIM_API_KEY` environment variable)
34+
- **FAIM API key**: Register at [https://faim.it.com/](https://faim.it.com/) to get your `FAIM_API_KEY`
5535

5636
### Option 1: Install from npm (Recommended)
5737

5838
```bash
5939
npm install @faim-group/mcp
6040
```
6141

62-
Then configure Claude Desktop to use it:
42+
Then configure your client to use it:
6343

6444
```json
6545
{
@@ -81,7 +61,7 @@ Or if installed globally:
8161
npm install -g @faim-group/mcp
8262
```
8363

84-
Then in Claude Desktop config:
64+
Then in config:
8565

8666
```json
8767
{
@@ -116,7 +96,7 @@ npm test
11696
npm run lint
11797
```
11898

119-
Then in Claude Desktop config, use the local path:
99+
Then use the local path:
120100

121101
```json
122102
{
@@ -140,9 +120,6 @@ Then in Claude Desktop config, use the local path:
140120
# Required: Your FAIM API key
141121
export FAIM_API_KEY="your-api-key-here"
142122

143-
# Optional: Custom API base URL (defaults to production)
144-
export FAIM_API_BASE_URL="https://api.faim.it.com"
145-
146123
# Optional: Set to non-production for verbose logging
147124
export NODE_ENV=development
148125
```
@@ -151,15 +128,6 @@ export NODE_ENV=development
151128

152129
This server implements the **Model Context Protocol (MCP)**, an open protocol for connecting AI assistants to external tools and data sources. MCP is not limited to Claude - it works with any application that implements an MCP client.
153130

154-
### Supported Clients & Platforms
155-
156-
- **Claude Desktop** - Native MCP integration
157-
- **Claude.ai Web** - Via MCP support
158-
- **IDE Extensions** - VS Code (Cline), Zed, Continue.dev, and others
159-
- **AI Agent Frameworks** - LangChain, AutoGPT, CrewAI, etc.
160-
- **Custom MCP Clients** - JSON-RPC 2.0 over stdio
161-
- **Any LLM** - Via MCP client implementation
162-
163131
### Using with Any LLM or System
164132

165133
This server implements the standard MCP protocol and works with any application that implements an MCP client:
@@ -252,7 +220,7 @@ Performs time series forecasting using FAIM models.
252220
"name": "forecast",
253221
"arguments": {
254222
"model": "chronos2",
255-
"x": [[1, 2], [3, 4], [5, 6]],
223+
"x": [[[100, 50], [102, 51], [105, 52]]],
256224
"horizon": 5,
257225
"output_type": "quantiles",
258226
"quantiles": [0.1, 0.5, 0.9]
@@ -317,73 +285,6 @@ faim-mcp/
317285
└── package.json, tsconfig.json, tsup.config.ts, vitest.config.ts
318286
```
319287

320-
## Architecture
321-
322-
### Client Management (`src/utils/client.ts`)
323-
324-
- **Singleton Pattern**: Single FAIM client instance across all requests
325-
- **Lazy Initialization**: Client created when first needed
326-
- **Error Handling**: Fails fast if API key is missing at startup
327-
328-
### Input Validation (`src/utils/validation.ts`)
329-
330-
- **Format Normalization**: Converts 1D/2D arrays to required 3D format
331-
- **Comprehensive Checks**: Validates all parameters before API calls
332-
- **Helpful Errors**: Clear, actionable error messages
333-
- **Type Safety**: Full TypeScript support
334-
335-
### Error Handling (`src/utils/errors.ts`)
336-
337-
- **Error Classification**: Identifies error types (auth, validation, network, etc.)
338-
- **User-Friendly Messages**: Transforms technical errors to helpful guidance
339-
- **Retryable Detection**: Identifies transient vs permanent failures
340-
- **Structured Logging**: Production-ready error reporting
341-
342-
### Tools Implementation
343-
344-
#### `list_models` Tool
345-
- Stateless operation (no API calls)
346-
- Returns hardcoded model information
347-
- Used for discovery and capability checking
348-
- Fast and reliable
349-
350-
#### `forecast` Tool
351-
- Validates input comprehensively
352-
- Normalizes arrays to SDK format
353-
- Routes to appropriate model (Chronos2 or TiRex)
354-
- Transforms SDK responses
355-
- Comprehensive error handling
356-
357-
## Error Handling
358-
359-
The server uses a `ToolResult<T>` pattern where all tools return either success or failure:
360-
361-
```typescript
362-
// Success response
363-
{
364-
success: true,
365-
data: { /* tool-specific response */ }
366-
}
367-
368-
// Error response
369-
{
370-
success: false,
371-
error: {
372-
error_code: "VALIDATION_ERROR",
373-
message: "Human-readable error message",
374-
details: "Additional context",
375-
field: "x" // If field-specific
376-
}
377-
}
378-
```
379-
380-
### Error Codes
381-
382-
- **Validation**: `INVALID_PARAMETER`, `MISSING_REQUIRED_FIELD`, `INVALID_VALUE_RANGE`
383-
- **Authentication**: `INVALID_API_KEY`, `AUTHENTICATION_FAILED`
384-
- **Network**: `NETWORK_ERROR`, `TIMEOUT_ERROR`
385-
- **Server**: `INTERNAL_SERVER_ERROR`, `RESOURCE_EXHAUSTED`
386-
387288
## Testing
388289

389290
The project includes comprehensive tests for:
@@ -400,23 +301,6 @@ npm run test:coverage # Run with coverage report
400301
npm run test:ui # Run with UI dashboard
401302
```
402303

403-
## Development
404-
405-
### Adding New Tools
406-
407-
1. Create a new file in `src/tools/`
408-
2. Implement the tool handler function
409-
3. Export `TOOL_DEFINITION` constant
410-
4. Add to server's tool handlers
411-
5. Add tests in `tests/tools/`
412-
413-
### Adding New Utilities
414-
415-
1. Create in `src/utils/`
416-
2. Keep single responsibility
417-
3. Add comprehensive comments
418-
4. Export for use by tools
419-
5. Add unit tests
420304

421305
### Debugging
422306

@@ -449,31 +333,6 @@ Outputs:
449333
- [ ] Deploy `dist/` directory
450334
- [ ] Run `node dist/index.js` as the server process
451335

452-
## Performance Considerations
453-
454-
- **Client Initialization**: Done once at startup, not per-request
455-
- **Array Normalization**: Minimal overhead, done in-memory
456-
- **Error Messages**: Only detailed on actual errors, no overhead on success
457-
- **Logging**: Disabled in production mode
458-
- **Type Safety**: Zero runtime cost, compile-time only
459-
460-
## Security
461-
462-
- **API Key Management**: Environment variable, never logged
463-
- **Input Validation**: All inputs validated before API calls
464-
- **Error Messages**: Don't expose internal system details
465-
- **Timeout Handling**: Configurable per-request timeouts
466-
- **Type Safety**: Full TypeScript ensures type safety
467-
468-
## Documentation Comments
469-
470-
All source files include comprehensive LLM-friendly comments explaining:
471-
- **What** each component does
472-
- **Why** it's designed that way
473-
- **How** it integrates with other parts
474-
- **Edge cases** and important considerations
475-
476-
This helps both humans and LLMs understand the codebase.
477336

478337
## Troubleshooting
479338

@@ -489,11 +348,6 @@ npm install
489348
npm run build
490349
```
491350

492-
### Tests failing
493-
```bash
494-
npm run lint # Check TypeScript errors
495-
npm test # Run tests with detailed output
496-
```
497351

498352
### Server not responding
499353
- Check that stdout/stderr are properly connected
@@ -504,11 +358,3 @@ npm test # Run tests with detailed output
504358
## License
505359

506360
MIT
507-
508-
## Support
509-
510-
For issues or questions:
511-
1. Check the comprehensive code comments
512-
2. Review test files for usage examples
513-
3. Check error messages for helpful suggestions
514-
4. Review architecture documentation above

package.json

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@faim-group/mcp",
3-
"version": "0.1.0",
3+
"version": "0.1.2",
44
"description": "MCP server for FAIM forecasting SDK - Enables Claude to perform time series forecasting using Chronos2 and TiRex models",
55
"main": "dist/index.js",
66
"types": "dist/index.d.ts",
@@ -33,6 +33,14 @@
3333
],
3434
"author": "",
3535
"license": "MIT",
36+
"homepage": "https://faim.it.com/",
37+
"repository": {
38+
"type": "git",
39+
"url": "https://github.com/S-FM/faim-mcp.git"
40+
},
41+
"bugs": {
42+
"url": "https://github.com/S-FM/faim-mcp/issues"
43+
},
3644
"type": "module",
3745
"dependencies": {
3846
"@faim-group/sdk-forecasting": "^0.1.1",

src/utils/validation.ts

Lines changed: 39 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -313,38 +313,63 @@ function validateArrayInput(x: unknown): { error_code: string; message: string;
313313
/**
314314
* Normalizes user input arrays to 3D format required by SDK
315315
*
316-
* The FAIM SDK expects data in shape [batch, sequence_length, num_features]:
317-
* - batch: Multiple independent time series (typically 1 for single forecast)
318-
* - sequence_length: Number of historical steps
319-
* - num_features: Number of variables (1 for univariate, >1 for multivariate)
316+
* The FAIM SDK expects data in shape [batch, sequence_length, num_features] where:
317+
* - b (batch): Multiple independent time series (typically 1 for single forecast)
318+
* - c (sequence_length): Number of historical timesteps
319+
* - f (num_features): Number of variables (1 for univariate, >1 for multivariate)
320320
*
321-
* This function accepts user-friendly formats:
322-
* - 1D [1, 2, 3] → [[[1], [2], [3]]]
323-
* - 2D [[1, 2], [3, 4]] → [[[1, 2], [3, 4]]] (multivariate)
324-
* - 3D (already correct) → unchanged
321+
* INPUT FORMATS ACCEPTED (all automatically converted to 3D):
322+
*
323+
* 1. 1D ARRAY - Univariate time series with shape (c,):
324+
* Input: [1, 2, 3, 4, 5]
325+
* Meaning: 5 univariate timesteps
326+
* Output: [[[1], [2], [3], [4], [5]]] (shape: [1, 5, 1] = [b=1, c=5, f=1])
327+
*
328+
* 2. 3D ARRAY - Already in correct format with shape (b, c, f):
329+
* Input: [[[1], [2], [3]]]
330+
* Meaning: 1 batch, 3 timesteps, 1 feature (univariate)
331+
* Output: [[[1], [2], [3]]] (unchanged, shape: [1, 3, 1])
332+
*
333+
* Input: [[[100, 50, 200], [102, 51, 205]]]
334+
* Meaning: 1 batch, 2 timesteps, 3 features (multivariate)
335+
* Output: [[[100, 50, 200], [102, 51, 205]]] (unchanged, shape: [1, 2, 3])
336+
*
337+
* Note: 2D arrays [[1, 2], [3, 4]] are also accepted (treated as multivariate single batch)
325338
*
326339
* @param input - Raw input from user (1D, 2D, or 3D array)
327-
* @returns {number[][][]} Normalized 3D array
340+
* @returns {number[][][]} Normalized 3D array with shape [b, c, f]
328341
*
329-
* Example:
342+
* Example (for LLMs):
330343
* ```typescript
331-
* normalizeInput([1, 2, 3, 4, 5]) // → [[[1], [2], [3], [4], [5]]]
344+
* // 1D input: Single univariate time series
345+
* normalizeInput([1, 2, 3, 4, 5])
346+
* // Returns: [[[1], [2], [3], [4], [5]]]
347+
* // Shape: [b=1, c=5, f=1]
348+
*
349+
* // 3D input: Already correct format (multivariate, single batch)
350+
* normalizeInput([[[100, 50], [102, 51], [105, 52]]])
351+
* // Returns: [[[100, 50], [102, 51], [105, 52]]] (unchanged)
352+
* // Shape: [b=1, c=3, f=2]
332353
* ```
333354
*/
334355
export function normalizeInput(input: number[] | number[][] | number[][][]): number[][][] {
335-
// Already 3D? Return as-is
356+
// Already 3D? Return as-is (shape: [b, c, f])
336357
if (Array.isArray(input[0]) && Array.isArray(input[0][0])) {
337358
return input as number[][][];
338359
}
339360

340-
// 1D array [1, 2, 3]
361+
// 1D array (shape: c,) - Univariate time series
362+
// Example: [1, 2, 3, 4, 5]
363+
// Transform to 3D: [[[1], [2], [3], [4], [5]]] (shape: [b=1, c=5, f=1])
341364
if (typeof input[0] === 'number') {
342365
// Convert each scalar to a 1-element array [n] → [[n]]
343366
// Then wrap in batch dimension [[[1], [2], [3]]]
344367
return [(input as number[]).map((val) => [val])];
345368
}
346369

347-
// 2D array [[1, 2], [3, 4]] - each row is a timestep with features
370+
// 2D array (shape: c, f) - Multivariate single batch
371+
// Example: [[1, 2], [3, 4]] represents 2 timesteps with 2 features each
372+
// Transform to 3D: [[[1, 2], [3, 4]]] (shape: [b=1, c=2, f=2])
348373
// Wrap in batch dimension: [[[1, 2], [3, 4]]]
349374
return [input as number[][]];
350375
}

0 commit comments

Comments
 (0)