stockquotes-mcp 1.0.4 → 1.0.5
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 +20 -10
- package/dist/errors.d.ts +16 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +29 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.js +21 -16
- package/dist/index.js.map +1 -1
- package/dist/logger.d.ts +3 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +20 -0
- package/dist/logger.js.map +1 -0
- package/dist/server.d.ts +3 -3
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +0 -3
- package/dist/server.js.map +1 -1
- package/dist/stockQuotesService.d.ts +1 -0
- package/dist/stockQuotesService.d.ts.map +1 -1
- package/dist/stockQuotesService.js +35 -10
- package/dist/stockQuotesService.js.map +1 -1
- package/dist/toolRegistration.d.ts.map +1 -1
- package/dist/toolRegistration.js +8 -25
- package/dist/toolRegistration.js.map +1 -1
- package/dist/transports/HttpTransportStrategy.d.ts +6 -6
- package/dist/transports/HttpTransportStrategy.d.ts.map +1 -1
- package/dist/transports/HttpTransportStrategy.js +27 -13
- package/dist/transports/HttpTransportStrategy.js.map +1 -1
- package/dist/transports/StdioTransportStrategy.d.ts +2 -5
- package/dist/transports/StdioTransportStrategy.d.ts.map +1 -1
- package/dist/transports/StdioTransportStrategy.js +5 -8
- package/dist/transports/StdioTransportStrategy.js.map +1 -1
- package/dist/types.d.ts +10 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +16 -0
- package/dist/types.js.map +1 -1
- package/dist/yahooFinanceClient.d.ts +15 -8
- package/dist/yahooFinanceClient.d.ts.map +1 -1
- package/dist/yahooFinanceClient.js.map +1 -1
- package/package.json +15 -3
package/README.md
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
[](https://github.com/lionelschiepers/StockQuotes.MCP/actions/workflows/build.yml)
|
|
4
4
|
[](https://codecov.io/github/lionelschiepers/StockQuotes.MCP)
|
|
5
|
+
[](https://sonarcloud.io/summary/new_code?id=lionelschiepers_StockQuotes.MCP)
|
|
5
6
|
[](https://opensource.org/licenses/MIT)
|
|
6
7
|
[](https://www.typescriptlang.org/)
|
|
7
8
|
[](https://modelcontextprotocol.io/)
|
|
@@ -52,7 +53,17 @@ It transforms your AI from a static text generator into a dynamic financial anal
|
|
|
52
53
|
|
|
53
54
|
## ⚡ Quick Start
|
|
54
55
|
|
|
55
|
-
|
|
56
|
+
The fastest way to run the server is using `npx`:
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
# Start in Stdio Mode (default for most MCP clients)
|
|
60
|
+
npx stockquotes-mcp --transport stdio
|
|
61
|
+
|
|
62
|
+
# Start as an HTTP/SSE Server
|
|
63
|
+
npx stockquotes-mcp --transport http
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Alternatively, for local development:
|
|
56
67
|
|
|
57
68
|
```bash
|
|
58
69
|
# Clone and Install
|
|
@@ -60,10 +71,8 @@ git clone https://github.com/lionelschiepers/StockQuotes.MCP.git
|
|
|
60
71
|
cd StockQuotes.MCP
|
|
61
72
|
npm install
|
|
62
73
|
|
|
63
|
-
# Build
|
|
74
|
+
# Build and Start
|
|
64
75
|
npm run build
|
|
65
|
-
|
|
66
|
-
# Start (Stdio Mode - default for most MCP clients)
|
|
67
76
|
npm run start:stdio
|
|
68
77
|
```
|
|
69
78
|
|
|
@@ -161,8 +170,8 @@ To use with [Cline](https://github.com/cline/cline), add this to your MCP settin
|
|
|
161
170
|
{
|
|
162
171
|
"mcpServers": {
|
|
163
172
|
"stock-quotes": {
|
|
164
|
-
"command": "
|
|
165
|
-
"args": ["
|
|
173
|
+
"command": "npx",
|
|
174
|
+
"args": ["-y", "stockquotes-mcp", "--transport", "stdio"],
|
|
166
175
|
"disabled": false,
|
|
167
176
|
"autoApprove": []
|
|
168
177
|
}
|
|
@@ -172,11 +181,11 @@ To use with [Cline](https://github.com/cline/cline), add this to your MCP settin
|
|
|
172
181
|
|
|
173
182
|
### Gemini CLI
|
|
174
183
|
|
|
175
|
-
Integrate with the Gemini CLI tool
|
|
184
|
+
Integrate with the Gemini CLI tool:
|
|
176
185
|
|
|
177
186
|
**Method 1: Direct Command**
|
|
178
187
|
```bash
|
|
179
|
-
gemini mcp add stock-quotes
|
|
188
|
+
gemini mcp add stock-quotes npx "-y stockquotes-mcp --transport stdio"
|
|
180
189
|
```
|
|
181
190
|
|
|
182
191
|
**Method 2: Settings Configuration**
|
|
@@ -187,9 +196,10 @@ Edit your `~/.gemini/settings.json`:
|
|
|
187
196
|
{
|
|
188
197
|
"mcpServers": {
|
|
189
198
|
"stock-quotes": {
|
|
190
|
-
"command": "
|
|
199
|
+
"command": "npx",
|
|
191
200
|
"args": [
|
|
192
|
-
"
|
|
201
|
+
"-y",
|
|
202
|
+
"stockquotes-mcp",
|
|
193
203
|
"--transport",
|
|
194
204
|
"stdio"
|
|
195
205
|
]
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export declare class AppError extends Error {
|
|
2
|
+
message: string;
|
|
3
|
+
statusCode: number;
|
|
4
|
+
code: string;
|
|
5
|
+
constructor(message: string, statusCode?: number, code?: string);
|
|
6
|
+
}
|
|
7
|
+
export declare class NotFoundError extends AppError {
|
|
8
|
+
constructor(message: string);
|
|
9
|
+
}
|
|
10
|
+
export declare class RateLimitError extends AppError {
|
|
11
|
+
constructor(message?: string);
|
|
12
|
+
}
|
|
13
|
+
export declare class ValidationError extends AppError {
|
|
14
|
+
constructor(message: string);
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,qBAAa,QAAS,SAAQ,KAAK;IAExB,OAAO,EAAE,MAAM;IACf,UAAU,EAAE,MAAM;IAClB,IAAI,EAAE,MAAM;gBAFZ,OAAO,EAAE,MAAM,EACf,UAAU,GAAE,MAAY,EACxB,IAAI,GAAE,MAAyB;CAMzC;AAED,qBAAa,aAAc,SAAQ,QAAQ;gBAC7B,OAAO,EAAE,MAAM;CAG5B;AAED,qBAAa,cAAe,SAAQ,QAAQ;gBAC9B,OAAO,GAAE,MAAsD;CAG5E;AAED,qBAAa,eAAgB,SAAQ,QAAQ;gBAC/B,OAAO,EAAE,MAAM;CAG5B"}
|
package/dist/errors.js
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export class AppError extends Error {
|
|
2
|
+
message;
|
|
3
|
+
statusCode;
|
|
4
|
+
code;
|
|
5
|
+
constructor(message, statusCode = 500, code = 'INTERNAL_ERROR') {
|
|
6
|
+
super(message);
|
|
7
|
+
this.message = message;
|
|
8
|
+
this.statusCode = statusCode;
|
|
9
|
+
this.code = code;
|
|
10
|
+
this.name = this.constructor.name;
|
|
11
|
+
Error.captureStackTrace(this, this.constructor);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
export class NotFoundError extends AppError {
|
|
15
|
+
constructor(message) {
|
|
16
|
+
super(message, 404, 'NOT_FOUND');
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
export class RateLimitError extends AppError {
|
|
20
|
+
constructor(message = 'Rate limit exceeded. Please try again later') {
|
|
21
|
+
super(message, 429, 'RATE_LIMIT_EXCEEDED');
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
export class ValidationError extends AppError {
|
|
25
|
+
constructor(message) {
|
|
26
|
+
super(message, 400, 'VALIDATION_ERROR');
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,QAAS,SAAQ,KAAK;IAExB;IACA;IACA;IAHT,YACS,OAAe,EACf,aAAqB,GAAG,EACxB,OAAe,gBAAgB;QAEtC,KAAK,CAAC,OAAO,CAAC,CAAC;QAJR,YAAO,GAAP,OAAO,CAAQ;QACf,eAAU,GAAV,UAAU,CAAc;QACxB,SAAI,GAAJ,IAAI,CAA2B;QAGtC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC;QAClC,KAAK,CAAC,iBAAiB,CAAC,IAAI,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;IAClD,CAAC;CACF;AAED,MAAM,OAAO,aAAc,SAAQ,QAAQ;IACzC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,EAAE,GAAG,EAAE,WAAW,CAAC,CAAC;IACnC,CAAC;CACF;AAED,MAAM,OAAO,cAAe,SAAQ,QAAQ;IAC1C,YAAY,UAAkB,6CAA6C;QACzE,KAAK,CAAC,OAAO,EAAE,GAAG,EAAE,qBAAqB,CAAC,CAAC;IAC7C,CAAC;CACF;AAED,MAAM,OAAO,eAAgB,SAAQ,QAAQ;IAC3C,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,EAAE,GAAG,EAAE,kBAAkB,CAAC,CAAC;IAC1C,CAAC;CACF"}
|
package/dist/index.js
CHANGED
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
* node dist/index.js --transport http # Start with HTTP transport (port 3000)
|
|
11
11
|
*/
|
|
12
12
|
import { createServer } from './server.js';
|
|
13
|
+
import { logger } from './logger.js';
|
|
13
14
|
// Parse command line arguments
|
|
14
15
|
function parseArgs() {
|
|
15
16
|
const args = process.argv.slice(2);
|
|
@@ -29,8 +30,7 @@ function parseArgs() {
|
|
|
29
30
|
result.transport = transport;
|
|
30
31
|
}
|
|
31
32
|
else {
|
|
32
|
-
|
|
33
|
-
console.error('Valid transports: stdio, http');
|
|
33
|
+
logger.error(`Invalid transport: ${transport}`);
|
|
34
34
|
process.exit(1);
|
|
35
35
|
}
|
|
36
36
|
}
|
|
@@ -40,7 +40,7 @@ function parseArgs() {
|
|
|
40
40
|
if (i + 1 < args.length) {
|
|
41
41
|
result.httpPort = Number.parseInt(args[++i], 10);
|
|
42
42
|
if (Number.isNaN(result.httpPort) || result.httpPort <= 0 || result.httpPort > 65535) {
|
|
43
|
-
|
|
43
|
+
logger.error('Invalid HTTP port. Port must be between 1 and 65535');
|
|
44
44
|
process.exit(1);
|
|
45
45
|
}
|
|
46
46
|
}
|
|
@@ -58,7 +58,7 @@ function parseArgs() {
|
|
|
58
58
|
break;
|
|
59
59
|
case '--version':
|
|
60
60
|
case '-v':
|
|
61
|
-
console.log('StockQuotes.MCP version 1.0.
|
|
61
|
+
console.log('StockQuotes.MCP version 1.0.4');
|
|
62
62
|
process.exit(0);
|
|
63
63
|
}
|
|
64
64
|
}
|
|
@@ -106,41 +106,46 @@ For more information, visit: https://github.com/lionelschiepers/StockQuotes.MCP
|
|
|
106
106
|
* Main function to start the server
|
|
107
107
|
*/
|
|
108
108
|
async function main() {
|
|
109
|
-
|
|
110
|
-
console.log('========================');
|
|
109
|
+
logger.info('MCP Stock Quotes Server starting');
|
|
111
110
|
const args = parseArgs();
|
|
112
|
-
|
|
111
|
+
logger.info(`Starting server with ${args.transport} transport...`, {
|
|
112
|
+
transport: args.transport,
|
|
113
|
+
port: args.httpPort,
|
|
114
|
+
host: args.httpHost,
|
|
115
|
+
});
|
|
113
116
|
try {
|
|
114
117
|
await createServer({
|
|
115
118
|
name: 'stock-quotes-server',
|
|
116
|
-
version: '1.0.
|
|
119
|
+
version: '1.0.4',
|
|
117
120
|
transport: args.transport,
|
|
118
121
|
httpPort: args.httpPort,
|
|
119
122
|
httpHost: args.httpHost,
|
|
120
123
|
});
|
|
121
|
-
|
|
124
|
+
logger.info('Server started successfully');
|
|
122
125
|
if (args.transport === 'http') {
|
|
123
|
-
console.log('Press Ctrl+C to stop the server');
|
|
124
126
|
await new Promise(() => { });
|
|
125
127
|
}
|
|
126
128
|
}
|
|
127
129
|
catch (error) {
|
|
128
|
-
|
|
130
|
+
logger.error('Failed to start server', { error });
|
|
129
131
|
process.exit(1);
|
|
130
132
|
}
|
|
131
133
|
}
|
|
132
134
|
// Handle graceful shutdown
|
|
133
135
|
process.on('SIGINT', () => {
|
|
134
|
-
|
|
136
|
+
logger.info('Shutting down server...');
|
|
135
137
|
process.exit(0);
|
|
136
138
|
});
|
|
137
139
|
process.on('SIGTERM', () => {
|
|
138
|
-
|
|
140
|
+
logger.info('Shutting down server...');
|
|
139
141
|
process.exit(0);
|
|
140
142
|
});
|
|
141
143
|
// Start the server
|
|
142
|
-
|
|
143
|
-
|
|
144
|
+
try {
|
|
145
|
+
await main();
|
|
146
|
+
}
|
|
147
|
+
catch (error) {
|
|
148
|
+
logger.error('Unhandled error', { error });
|
|
144
149
|
process.exit(1);
|
|
145
|
-
}
|
|
150
|
+
}
|
|
146
151
|
//# 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":";AAEA;;;;;;;;;GASG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/logger.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,SAAS,CAAC;AAY9B,eAAO,MAAM,MAAM,gBAajB,CAAC"}
|
package/dist/logger.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import winston from 'winston';
|
|
2
|
+
const { combine, timestamp, json, colorize, printf } = winston.format;
|
|
3
|
+
const consoleFormat = printf(({ level, message, timestamp, ...metadata }) => {
|
|
4
|
+
let msg = `${String(timestamp)} [${String(level)}]: ${String(message)}`;
|
|
5
|
+
if (Object.keys(metadata).length > 0) {
|
|
6
|
+
msg += ` ${JSON.stringify(metadata)}`;
|
|
7
|
+
}
|
|
8
|
+
return msg;
|
|
9
|
+
});
|
|
10
|
+
export const logger = winston.createLogger({
|
|
11
|
+
level: process.env.LOG_LEVEL ?? 'info',
|
|
12
|
+
format: combine(timestamp(), json()),
|
|
13
|
+
defaultMeta: { service: 'stockquotes-mcp' },
|
|
14
|
+
transports: [
|
|
15
|
+
new winston.transports.Console({
|
|
16
|
+
format: combine(timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }), colorize(), process.env.NODE_ENV === 'production' ? json() : consoleFormat),
|
|
17
|
+
}),
|
|
18
|
+
],
|
|
19
|
+
});
|
|
20
|
+
//# sourceMappingURL=logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,SAAS,CAAC;AAE9B,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC;AAEtE,MAAM,aAAa,GAAG,MAAM,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,GAAG,QAAQ,EAAE,EAAE,EAAE;IAC1E,IAAI,GAAG,GAAG,GAAG,MAAM,CAAC,SAAS,CAAC,KAAK,MAAM,CAAC,KAAK,CAAC,MAAM,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC;IACxE,IAAI,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACrC,GAAG,IAAI,IAAI,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,EAAE,CAAC;IACxC,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IACzC,KAAK,EAAE,OAAO,CAAC,GAAG,CAAC,SAAS,IAAI,MAAM;IACtC,MAAM,EAAE,OAAO,CAAC,SAAS,EAAE,EAAE,IAAI,EAAE,CAAC;IACpC,WAAW,EAAE,EAAE,OAAO,EAAE,iBAAiB,EAAE;IAC3C,UAAU,EAAE;QACV,IAAI,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC;YAC7B,MAAM,EAAE,OAAO,CACb,SAAS,CAAC,EAAE,MAAM,EAAE,qBAAqB,EAAE,CAAC,EAC5C,QAAQ,EAAE,EACV,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,aAAa,CAC/D;SACF,CAAC;KACH;CACF,CAAC,CAAC"}
|
package/dist/server.d.ts
CHANGED
|
@@ -4,9 +4,9 @@ import type { ServerConfig } from './types.js';
|
|
|
4
4
|
* MCP Server for Stock Quotes using Yahoo Finance
|
|
5
5
|
*/
|
|
6
6
|
export declare class StockQuotesServer {
|
|
7
|
-
private config;
|
|
8
|
-
private stockService;
|
|
9
|
-
private transportStrategy;
|
|
7
|
+
private readonly config;
|
|
8
|
+
private readonly stockService;
|
|
9
|
+
private readonly transportStrategy;
|
|
10
10
|
/**
|
|
11
11
|
* Create a new instance of the StockQuotesServer
|
|
12
12
|
* @param config - Server configuration
|
package/dist/server.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAIlE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAO/C;;GAEG;AACH,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAe;IACtC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAqB;IAClD,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAoB;IAEtD;;;;OAIG;gBACS,MAAM,EAAE,YAAY,EAAE,YAAY,EAAE,kBAAkB;IAMlE;;OAEG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAI9B;;;OAGG;IACH,MAAM,IAAI,OAAO;IAQjB;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAG7B;AAED;;GAEG;AACH,wBAAsB,YAAY,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAe7F"}
|
package/dist/server.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { StockQuotesService as StockQuotesServiceImpl } from './stockQuotesService.js';
|
|
2
|
-
import { registerToolsOnServer } from './toolRegistration.js';
|
|
3
2
|
import { TransportFactory } from './transports/TransportFactory.js';
|
|
4
3
|
import { YahooFinanceClient } from './yahooFinanceClient.js';
|
|
5
4
|
/**
|
|
@@ -23,8 +22,6 @@ export class StockQuotesServer {
|
|
|
23
22
|
* Connect to the appropriate transport using the strategy pattern
|
|
24
23
|
*/
|
|
25
24
|
async connect() {
|
|
26
|
-
const server = this.transportStrategy.getServer();
|
|
27
|
-
registerToolsOnServer(server, this.stockService);
|
|
28
25
|
await this.transportStrategy.connect();
|
|
29
26
|
}
|
|
30
27
|
/**
|
package/dist/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,IAAI,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AACvF,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,IAAI,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AACvF,OAAO,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AAGpE,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAM7D;;GAEG;AACH,MAAM,OAAO,iBAAiB;IACX,MAAM,CAAe;IACrB,YAAY,CAAqB;IACjC,iBAAiB,CAAoB;IAEtD;;;;OAIG;IACH,YAAY,MAAoB,EAAE,YAAgC;QAChE,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,YAAY,GAAG,YAAY,CAAC;QACjC,IAAI,CAAC,iBAAiB,GAAG,gBAAgB,CAAC,eAAe,CAAC,MAAM,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC;IACvF,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,OAAO;QACX,MAAM,IAAI,CAAC,iBAAiB,CAAC,OAAO,EAAE,CAAC;IACzC,CAAC;IAED;;;OAGG;IACH,MAAM;QACJ,MAAM,QAAQ,GAAG,IAAI,CAAC,iBAA0C,CAAC;QACjE,IAAI,OAAO,QAAQ,CAAC,MAAM,KAAK,UAAU,EAAE,CAAC;YAC1C,OAAO,QAAQ,CAAC,MAAM,EAAE,CAAC;QAC3B,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,kDAAkD,CAAC,CAAC;IACtE,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,KAAK;QACT,MAAM,IAAI,CAAC,iBAAiB,CAAC,KAAK,EAAE,CAAC;IACvC,CAAC;CACF;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,MAA8B;IAC/D,MAAM,YAAY,GAAiB;QACjC,IAAI,EAAE,qBAAqB;QAC3B,OAAO,EAAE,OAAO;QAChB,SAAS,EAAE,OAAO;QAClB,QAAQ,EAAE,IAAI;QACd,QAAQ,EAAE,SAAS;QACnB,GAAG,MAAM;KACV,CAAC;IAEF,MAAM,WAAW,GAAG,IAAI,kBAAkB,EAAE,CAAC;IAC7C,MAAM,YAAY,GAAG,IAAI,sBAAsB,CAAC,WAAW,CAAC,CAAC;IAC7D,MAAM,MAAM,GAAG,IAAI,iBAAiB,CAAC,YAAY,EAAE,YAAY,CAAC,CAAC;IACjE,MAAM,MAAM,CAAC,OAAO,EAAE,CAAC;IACvB,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stockQuotesService.d.ts","sourceRoot":"","sources":["../src/stockQuotesService.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"stockQuotesService.d.ts","sourceRoot":"","sources":["../src/stockQuotesService.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,cAAc,EACd,eAAe,EACf,kBAAkB,EAClB,iBAAiB,EAIlB,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAE3D;;GAEG;AACH,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAc;IAC1C,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAY;IAElC;;OAEG;gBACS,WAAW,EAAE,WAAW;IAMpC;;;;OAIG;IACG,QAAQ,CAAC,KAAK,EAAE,eAAe,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAuEnE;;;;OAIG;IACG,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC;IAepF;;;;OAIG;IACG,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,EAAE,CAAC;IAuCzD;;;;;;OAMG;IACG,iBAAiB,CACrB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,cAAc,EAAE,CAAC;CAiC7B"}
|
|
@@ -1,14 +1,20 @@
|
|
|
1
|
-
import { format } from 'date-fns';
|
|
1
|
+
import { addDays, format, parseISO } from 'date-fns';
|
|
2
|
+
import NodeCache from 'node-cache';
|
|
3
|
+
import { NotFoundError, RateLimitError } from './errors.js';
|
|
4
|
+
import { logger } from './logger.js';
|
|
2
5
|
/**
|
|
3
6
|
* Service for fetching stock quotes from Yahoo Finance
|
|
4
7
|
*/
|
|
5
8
|
export class StockQuotesService {
|
|
6
9
|
yahooClient;
|
|
10
|
+
cache;
|
|
7
11
|
/**
|
|
8
12
|
* Create a new instance of the StockQuotesService
|
|
9
13
|
*/
|
|
10
14
|
constructor(yahooClient) {
|
|
11
15
|
this.yahooClient = yahooClient;
|
|
16
|
+
// Cache for 5 minutes by default, check for expired keys every 60 seconds
|
|
17
|
+
this.cache = new NodeCache({ stdTTL: 300, checkperiod: 60 });
|
|
12
18
|
}
|
|
13
19
|
/**
|
|
14
20
|
* Fetch a stock quote for the given ticker symbol
|
|
@@ -17,16 +23,22 @@ export class StockQuotesService {
|
|
|
17
23
|
*/
|
|
18
24
|
async getQuote(input) {
|
|
19
25
|
const { ticker, fields } = input;
|
|
26
|
+
const cacheKey = `quote_${ticker}_${fields?.join(',') ?? 'all'}`;
|
|
27
|
+
const cachedResponse = this.cache.get(cacheKey);
|
|
28
|
+
if (cachedResponse) {
|
|
29
|
+
logger.debug('Cache hit for stock quote', { ticker, cacheKey });
|
|
30
|
+
return cachedResponse;
|
|
31
|
+
}
|
|
20
32
|
try {
|
|
21
33
|
const validFields = fields ? fields.filter((field) => field.length > 0) : undefined;
|
|
22
34
|
const options = validFields ? { fields: validFields } : undefined;
|
|
23
35
|
const result = await this.yahooClient.quote(ticker, options);
|
|
24
36
|
if (!result) {
|
|
25
|
-
throw new
|
|
37
|
+
throw new NotFoundError(`Stock ticker '${ticker}' not found`);
|
|
26
38
|
}
|
|
27
39
|
const quote = Array.isArray(result) ? result[0] : result;
|
|
28
40
|
if (!quote) {
|
|
29
|
-
throw new
|
|
41
|
+
throw new NotFoundError(`Stock ticker '${ticker}' not found`);
|
|
30
42
|
}
|
|
31
43
|
const response = {
|
|
32
44
|
symbol: quote.symbol ?? ticker,
|
|
@@ -53,15 +65,16 @@ export class StockQuotesService {
|
|
|
53
65
|
};
|
|
54
66
|
Object.keys(response).forEach((key) => response[key] === undefined &&
|
|
55
67
|
delete response[key]);
|
|
68
|
+
this.cache.set(cacheKey, response);
|
|
56
69
|
return response;
|
|
57
70
|
}
|
|
58
71
|
catch (error) {
|
|
59
72
|
if (error instanceof Error) {
|
|
60
73
|
if (error.message.includes('No definition') || error.message.includes('not found')) {
|
|
61
|
-
throw new
|
|
74
|
+
throw new NotFoundError(`Stock ticker '${ticker}' not found`);
|
|
62
75
|
}
|
|
63
76
|
if (error.message.includes('rate limit')) {
|
|
64
|
-
throw new
|
|
77
|
+
throw new RateLimitError();
|
|
65
78
|
}
|
|
66
79
|
}
|
|
67
80
|
throw error;
|
|
@@ -80,7 +93,7 @@ export class StockQuotesService {
|
|
|
80
93
|
results.set(ticker, quote);
|
|
81
94
|
}
|
|
82
95
|
catch (error) {
|
|
83
|
-
|
|
96
|
+
logger.error(`Failed to fetch quote for ${ticker}`, { ticker, error });
|
|
84
97
|
}
|
|
85
98
|
}
|
|
86
99
|
return results;
|
|
@@ -91,9 +104,15 @@ export class StockQuotesService {
|
|
|
91
104
|
* @returns Promise<Array<{symbol: string, name: string, exchange: string}>> - Search results
|
|
92
105
|
*/
|
|
93
106
|
async search(query) {
|
|
107
|
+
const cacheKey = `search_${query}`;
|
|
108
|
+
const cachedResults = this.cache.get(cacheKey);
|
|
109
|
+
if (cachedResults) {
|
|
110
|
+
logger.debug('Cache hit for search', { query, cacheKey });
|
|
111
|
+
return cachedResults;
|
|
112
|
+
}
|
|
94
113
|
const results = await this.yahooClient.search(query);
|
|
95
114
|
const quotes = results.quotes ?? [];
|
|
96
|
-
|
|
115
|
+
const searchResults = quotes
|
|
97
116
|
.filter((quote) => typeof quote.symbol === 'string' &&
|
|
98
117
|
typeof quote.exchange === 'string' &&
|
|
99
118
|
(typeof quote.shortname === 'string' || typeof quote.longname === 'string'))
|
|
@@ -102,6 +121,9 @@ export class StockQuotesService {
|
|
|
102
121
|
name: result.shortname ?? result.longname ?? '',
|
|
103
122
|
exchange: result.exchange,
|
|
104
123
|
}));
|
|
124
|
+
// Cache search results for 30 minutes
|
|
125
|
+
this.cache.set(cacheKey, searchResults, 1800);
|
|
126
|
+
return searchResults;
|
|
105
127
|
}
|
|
106
128
|
/**
|
|
107
129
|
* Fetches historical stock data for a given ticker, from a start date to an end date.
|
|
@@ -112,9 +134,12 @@ export class StockQuotesService {
|
|
|
112
134
|
*/
|
|
113
135
|
async getHistoricalData(ticker, fromDate, toDate) {
|
|
114
136
|
try {
|
|
137
|
+
// Yahoo Finance treats period2 as exclusive, so we add 1 day to include the end date
|
|
138
|
+
const toDateObj = parseISO(toDate);
|
|
139
|
+
const period2 = format(addDays(toDateObj, 1), 'yyyy-MM-dd');
|
|
115
140
|
const chart = await this.yahooClient.chart(ticker, {
|
|
116
141
|
period1: fromDate,
|
|
117
|
-
period2
|
|
142
|
+
period2,
|
|
118
143
|
});
|
|
119
144
|
const historicalData = [];
|
|
120
145
|
const quotes = chart.quotes ?? [];
|
|
@@ -132,8 +157,8 @@ export class StockQuotesService {
|
|
|
132
157
|
return historicalData;
|
|
133
158
|
}
|
|
134
159
|
catch (error) {
|
|
135
|
-
|
|
136
|
-
throw new
|
|
160
|
+
logger.error(`Error fetching historical data for ${ticker}`, { ticker, error });
|
|
161
|
+
throw new NotFoundError(`Could not fetch historical data for ${ticker}. Please check the ticker and date range.`);
|
|
137
162
|
}
|
|
138
163
|
}
|
|
139
164
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stockQuotesService.js","sourceRoot":"","sources":["../src/stockQuotesService.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"stockQuotesService.js","sourceRoot":"","sources":["../src/stockQuotesService.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"toolRegistration.d.ts","sourceRoot":"","sources":["../src/toolRegistration.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEzE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"toolRegistration.d.ts","sourceRoot":"","sources":["../src/toolRegistration.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEzE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAGlE;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,SAAS,EAAE,YAAY,EAAE,kBAAkB,GAAG,IAAI,CA0E/F"}
|
package/dist/toolRegistration.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { logger } from './logger.js';
|
|
2
|
+
import { HistoricalDataSchema, StockQuoteSchema, StockSearchSchema } from './types.js';
|
|
2
3
|
/**
|
|
3
4
|
* Register all MCP tools on a server instance
|
|
4
5
|
* @param server - MCP server instance to register tools on
|
|
@@ -10,15 +11,9 @@ export function registerToolsOnServer(server, stockService) {
|
|
|
10
11
|
description: 'Fetch current stock quote data from Yahoo Finance for a given ticker symbol. ' +
|
|
11
12
|
'Returns price, volume, market cap, P/E ratio, 52-week range, and other key metrics. ' +
|
|
12
13
|
'Supports stocks, ETFs, cryptocurrencies, and other financial instruments.',
|
|
13
|
-
inputSchema:
|
|
14
|
-
ticker: z.string().min(1).max(10).describe('Stock ticker symbol (e.g., AAPL, GOOGL, MSFT)'),
|
|
15
|
-
fields: z
|
|
16
|
-
.array(z.string())
|
|
17
|
-
.optional()
|
|
18
|
-
.describe('Optional list of specific fields to return'),
|
|
19
|
-
}),
|
|
14
|
+
inputSchema: StockQuoteSchema,
|
|
20
15
|
}, async ({ ticker, fields }) => {
|
|
21
|
-
|
|
16
|
+
logger.info('Fetching stock quote', { ticker, fields });
|
|
22
17
|
const quote = await stockService.getQuote({ ticker, fields });
|
|
23
18
|
return {
|
|
24
19
|
content: [
|
|
@@ -34,11 +29,9 @@ export function registerToolsOnServer(server, stockService) {
|
|
|
34
29
|
title: 'Search Stocks',
|
|
35
30
|
description: 'Search for stocks by company name or ticker symbol. ' +
|
|
36
31
|
'Returns matching results with symbol, name, and exchange information.',
|
|
37
|
-
inputSchema:
|
|
38
|
-
query: z.string().min(1).describe('Search query (company name or ticker)'),
|
|
39
|
-
}),
|
|
32
|
+
inputSchema: StockSearchSchema,
|
|
40
33
|
}, async ({ query }) => {
|
|
41
|
-
|
|
34
|
+
logger.info('Searching stocks', { query });
|
|
42
35
|
const results = await stockService.search(query);
|
|
43
36
|
return {
|
|
44
37
|
content: [
|
|
@@ -53,19 +46,9 @@ export function registerToolsOnServer(server, stockService) {
|
|
|
53
46
|
server.registerTool(`get_historical_data`, {
|
|
54
47
|
title: 'Get Historical Data for a TICKER',
|
|
55
48
|
description: 'Fetch historical stock data for a given ticker, from a start date to an end date. Returns an array of closing prices for each day.',
|
|
56
|
-
inputSchema:
|
|
57
|
-
ticker: z.string().min(1).max(10).describe('Stock ticker symbol (e.g., AAPL)'),
|
|
58
|
-
fromDate: z
|
|
59
|
-
.string()
|
|
60
|
-
.regex(/^\d{4}-\d{2}-\d{2}$/)
|
|
61
|
-
.describe('Start date in YYYY-MM-DD format'),
|
|
62
|
-
toDate: z
|
|
63
|
-
.string()
|
|
64
|
-
.regex(/^\d{4}-\d{2}-\d{2}$/)
|
|
65
|
-
.describe('End date in YYYY-MM-DD format'),
|
|
66
|
-
}),
|
|
49
|
+
inputSchema: HistoricalDataSchema,
|
|
67
50
|
}, async ({ ticker, fromDate, toDate }) => {
|
|
68
|
-
|
|
51
|
+
logger.info('Fetching historical data', { ticker, fromDate, toDate });
|
|
69
52
|
const closingPrices = await stockService.getHistoricalData(ticker, fromDate, toDate);
|
|
70
53
|
return {
|
|
71
54
|
content: [
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"toolRegistration.js","sourceRoot":"","sources":["../src/toolRegistration.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"toolRegistration.js","sourceRoot":"","sources":["../src/toolRegistration.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,OAAO,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAEvF;;;;GAIG;AACH,MAAM,UAAU,qBAAqB,CAAC,MAAiB,EAAE,YAAgC;IACvF,MAAM,CAAC,YAAY,CACjB,iBAAiB,EACjB;QACE,KAAK,EAAE,iBAAiB;QACxB,WAAW,EACT,+EAA+E;YAC/E,sFAAsF;YACtF,2EAA2E;QAC7E,WAAW,EAAE,gBAAgB;KAC9B,EACD,KAAK,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE;QAC3B,MAAM,CAAC,IAAI,CAAC,sBAAsB,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;QACxD,MAAM,KAAK,GAAG,MAAM,YAAY,CAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;QAE9D,OAAO;YACL,OAAO,EAAE;gBACP;oBACE,IAAI,EAAE,MAAM;oBACZ,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;iBACrC;aACF;YACD,iBAAiB,EAAE,KAAK;SACzB,CAAC;IACJ,CAAC,CACF,CAAC;IAEF,MAAM,CAAC,YAAY,CACjB,eAAe,EACf;QACE,KAAK,EAAE,eAAe;QACtB,WAAW,EACT,sDAAsD;YACtD,uEAAuE;QACzE,WAAW,EAAE,iBAAiB;KAC/B,EACD,KAAK,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE;QAClB,MAAM,CAAC,IAAI,CAAC,kBAAkB,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;QAC3C,MAAM,OAAO,GAAG,MAAM,YAAY,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAEjD,OAAO;YACL,OAAO,EAAE;gBACP;oBACE,IAAI,EAAE,MAAM;oBACZ,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;iBACvC;aACF;YACD,iBAAiB,EAAE,EAAE,OAAO,EAAE;SAC/B,CAAC;IACJ,CAAC,CACF,CAAC;IAEF,MAAM,CAAC,YAAY,CACjB,qBAAqB,EACrB;QACE,KAAK,EAAE,kCAAkC;QACzC,WAAW,EACT,oIAAoI;QACtI,WAAW,EAAE,oBAAoB;KAClC,EACD,KAAK,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE;QACrC,MAAM,CAAC,IAAI,CAAC,0BAA0B,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC;QACtE,MAAM,aAAa,GAAG,MAAM,YAAY,CAAC,iBAAiB,CAAC,MAAM,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;QACrF,OAAO;YACL,OAAO,EAAE;gBACP;oBACE,IAAI,EAAE,MAAM;oBACZ,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,aAAa,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;iBACjD;aACF;YACD,iBAAiB,EAAE,EAAE,aAAa,EAAE;SACrC,CAAC;IACJ,CAAC,CACF,CAAC;AACJ,CAAC"}
|
|
@@ -7,13 +7,13 @@ import type { TransportStrategy } from './TransportStrategy.js';
|
|
|
7
7
|
* Handles connection via HTTP transport
|
|
8
8
|
*/
|
|
9
9
|
export declare class HttpTransportStrategy implements TransportStrategy {
|
|
10
|
-
private server;
|
|
11
|
-
private stockService;
|
|
12
|
-
private serverName;
|
|
13
|
-
private serverVersion;
|
|
10
|
+
private readonly server;
|
|
11
|
+
private readonly stockService;
|
|
12
|
+
private readonly serverName;
|
|
13
|
+
private readonly serverVersion;
|
|
14
14
|
private expressApp?;
|
|
15
|
-
private httpPort;
|
|
16
|
-
private httpHost;
|
|
15
|
+
private readonly httpPort;
|
|
16
|
+
private readonly httpHost;
|
|
17
17
|
private httpServer?;
|
|
18
18
|
/**
|
|
19
19
|
* Create a new HttpTransportStrategy instance
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HttpTransportStrategy.d.ts","sourceRoot":"","sources":["../../src/transports/HttpTransportStrategy.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,KAAK,OAAO,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"HttpTransportStrategy.d.ts","sourceRoot":"","sources":["../../src/transports/HttpTransportStrategy.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,KAAK,OAAO,MAAM,SAAS,CAAC;AAInC,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAEnE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAEhE;;;GAGG;AACH,qBAAa,qBAAsB,YAAW,iBAAiB;IAC7D,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAY;IACnC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAqB;IAClD,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAS;IACvC,OAAO,CAAC,UAAU,CAAC,CAAsB;IACzC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,UAAU,CAAC,CAA4C;IAE/D;;;;;;;OAOG;gBAED,UAAU,EAAE,MAAM,EAClB,aAAa,EAAE,MAAM,EACrB,YAAY,EAAE,kBAAkB,EAChC,QAAQ,EAAE,MAAM,EAChB,QAAQ,GAAE,MAAkB;IAc9B;;OAEG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IA2B9B;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAsF1B;;OAEG;IACH,OAAO,IAAI,MAAM;IAIjB;;OAEG;IACH,SAAS,IAAI,SAAS;IAItB;;OAEG;IACH,MAAM,IAAI,OAAO,CAAC,WAAW;IAO7B;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAU7B"}
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { createMcpExpressApp } from '@modelcontextprotocol/sdk/server/express.js';
|
|
2
2
|
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
3
3
|
import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
|
|
4
|
+
import { rateLimit } from 'express-rate-limit';
|
|
5
|
+
import helmet from 'helmet';
|
|
6
|
+
import { logger } from '../logger.js';
|
|
4
7
|
import { registerToolsOnServer } from '../toolRegistration.js';
|
|
5
8
|
/**
|
|
6
9
|
* HTTP Transport Strategy
|
|
@@ -33,6 +36,7 @@ export class HttpTransportStrategy {
|
|
|
33
36
|
name: serverName,
|
|
34
37
|
version: serverVersion,
|
|
35
38
|
});
|
|
39
|
+
registerToolsOnServer(this.server, this.stockService);
|
|
36
40
|
}
|
|
37
41
|
/**
|
|
38
42
|
* Connect using HTTP transport
|
|
@@ -46,15 +50,15 @@ export class HttpTransportStrategy {
|
|
|
46
50
|
return;
|
|
47
51
|
}
|
|
48
52
|
this.httpServer.on('listening', () => {
|
|
49
|
-
|
|
53
|
+
logger.info(`MCP Server running on http://localhost:${this.httpPort}/mcp`);
|
|
50
54
|
resolve();
|
|
51
55
|
});
|
|
52
56
|
this.httpServer.on('error', (error) => {
|
|
53
57
|
if (error.code === 'EADDRINUSE') {
|
|
54
|
-
|
|
58
|
+
logger.error(`Port ${this.httpPort} is already in use`, { port: this.httpPort });
|
|
55
59
|
}
|
|
56
60
|
else {
|
|
57
|
-
|
|
61
|
+
logger.error(`Error starting HTTP server: ${error.message}`, { error });
|
|
58
62
|
}
|
|
59
63
|
reject(new Error(`Failed to start HTTP server: ${error.message}`));
|
|
60
64
|
});
|
|
@@ -65,32 +69,42 @@ export class HttpTransportStrategy {
|
|
|
65
69
|
*/
|
|
66
70
|
setupExpressRoutes() {
|
|
67
71
|
this.expressApp ??= createMcpExpressApp({ host: this.httpHost });
|
|
72
|
+
// Security headers
|
|
73
|
+
this.expressApp.use(helmet());
|
|
74
|
+
// Apply rate limiting to all routes
|
|
75
|
+
const limiter = rateLimit({
|
|
76
|
+
windowMs: 15 * 60 * 1000, // 15 minutes
|
|
77
|
+
max: 100, // limit each IP to 100 requests per windowMs
|
|
78
|
+
standardHeaders: true,
|
|
79
|
+
legacyHeaders: false,
|
|
80
|
+
message: {
|
|
81
|
+
jsonrpc: '2.0',
|
|
82
|
+
error: {
|
|
83
|
+
code: -32001,
|
|
84
|
+
message: 'Too many requests, please try again later.',
|
|
85
|
+
},
|
|
86
|
+
id: null,
|
|
87
|
+
},
|
|
88
|
+
});
|
|
89
|
+
this.expressApp.use(limiter);
|
|
68
90
|
// Main MCP endpoint for stateless Streamable HTTP
|
|
69
91
|
this.expressApp.post('/mcp', async (req, res) => {
|
|
70
92
|
try {
|
|
71
|
-
// Create a new MCP server instance for each request (stateless)
|
|
72
|
-
const server = new McpServer({
|
|
73
|
-
name: this.serverName,
|
|
74
|
-
version: this.serverVersion,
|
|
75
|
-
});
|
|
76
|
-
// Register tools on the new server instance
|
|
77
|
-
registerToolsOnServer(server, this.stockService);
|
|
78
93
|
// Create stateless transport (no session tracking)
|
|
79
94
|
const transport = new StreamableHTTPServerTransport({
|
|
80
95
|
sessionIdGenerator: undefined, // Stateless - no session tracking
|
|
81
96
|
});
|
|
82
97
|
// Connect server to transport
|
|
83
|
-
await server.connect(transport);
|
|
98
|
+
await this.server.connect(transport);
|
|
84
99
|
// Handle the request
|
|
85
100
|
await transport.handleRequest(req, res, req.body);
|
|
86
101
|
// Clean up when request is closed
|
|
87
102
|
res.on('close', async () => {
|
|
88
103
|
await transport.close();
|
|
89
|
-
await server.close();
|
|
90
104
|
});
|
|
91
105
|
}
|
|
92
106
|
catch (error) {
|
|
93
|
-
|
|
107
|
+
logger.error('Error handling MCP request', { error });
|
|
94
108
|
if (!res.headersSent) {
|
|
95
109
|
res.status(500).json({
|
|
96
110
|
jsonrpc: '2.0',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HttpTransportStrategy.js","sourceRoot":"","sources":["../../src/transports/HttpTransportStrategy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,6CAA6C,CAAC;AAClF,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,6BAA6B,EAAE,MAAM,oDAAoD,CAAC;
|
|
1
|
+
{"version":3,"file":"HttpTransportStrategy.js","sourceRoot":"","sources":["../../src/transports/HttpTransportStrategy.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,14 +2,11 @@ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
|
2
2
|
import type { StockQuotesService } from '../stockQuotesService.js';
|
|
3
3
|
import type { TransportStrategy } from './TransportStrategy.js';
|
|
4
4
|
/**
|
|
5
|
-
*
|
|
5
|
+
* Standard I/O Transport Strategy
|
|
6
6
|
* Handles connection via stdio transport
|
|
7
7
|
*/
|
|
8
8
|
export declare class StdioTransportStrategy implements TransportStrategy {
|
|
9
|
-
private server;
|
|
10
|
-
private stockService;
|
|
11
|
-
private serverName;
|
|
12
|
-
private serverVersion;
|
|
9
|
+
private readonly server;
|
|
13
10
|
/**
|
|
14
11
|
* Create a new StdioTransportStrategy instance
|
|
15
12
|
* @param serverName - Name of the server
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"StdioTransportStrategy.d.ts","sourceRoot":"","sources":["../../src/transports/StdioTransportStrategy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;
|
|
1
|
+
{"version":3,"file":"StdioTransportStrategy.d.ts","sourceRoot":"","sources":["../../src/transports/StdioTransportStrategy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAIpE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AACnE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAEhE;;;GAGG;AACH,qBAAa,sBAAuB,YAAW,iBAAiB;IAC9D,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAY;IAEnC;;;;;OAKG;gBACS,UAAU,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,YAAY,EAAE,kBAAkB;IAQvF;;OAEG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAM9B;;OAEG;IACH,OAAO,IAAI,MAAM;IAIjB;;OAEG;IACH,SAAS,IAAI,SAAS;IAItB;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAG7B"}
|
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
2
|
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
3
|
+
import { logger } from '../logger.js';
|
|
4
|
+
import { registerToolsOnServer } from '../toolRegistration.js';
|
|
3
5
|
/**
|
|
4
|
-
*
|
|
6
|
+
* Standard I/O Transport Strategy
|
|
5
7
|
* Handles connection via stdio transport
|
|
6
8
|
*/
|
|
7
9
|
export class StdioTransportStrategy {
|
|
8
10
|
server;
|
|
9
|
-
stockService;
|
|
10
|
-
serverName;
|
|
11
|
-
serverVersion;
|
|
12
11
|
/**
|
|
13
12
|
* Create a new StdioTransportStrategy instance
|
|
14
13
|
* @param serverName - Name of the server
|
|
@@ -16,13 +15,11 @@ export class StdioTransportStrategy {
|
|
|
16
15
|
* @param stockService - Stock quotes service instance
|
|
17
16
|
*/
|
|
18
17
|
constructor(serverName, serverVersion, stockService) {
|
|
19
|
-
this.serverName = serverName;
|
|
20
|
-
this.serverVersion = serverVersion;
|
|
21
|
-
this.stockService = stockService;
|
|
22
18
|
this.server = new McpServer({
|
|
23
19
|
name: serverName,
|
|
24
20
|
version: serverVersion,
|
|
25
21
|
});
|
|
22
|
+
registerToolsOnServer(this.server, stockService);
|
|
26
23
|
}
|
|
27
24
|
/**
|
|
28
25
|
* Connect using stdio transport
|
|
@@ -30,7 +27,7 @@ export class StdioTransportStrategy {
|
|
|
30
27
|
async connect() {
|
|
31
28
|
const transport = new StdioServerTransport();
|
|
32
29
|
await this.server.connect(transport);
|
|
33
|
-
|
|
30
|
+
logger.info('MCP Server connected via stdio transport');
|
|
34
31
|
}
|
|
35
32
|
/**
|
|
36
33
|
* Get the transport type
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"StdioTransportStrategy.js","sourceRoot":"","sources":["../../src/transports/StdioTransportStrategy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;
|
|
1
|
+
{"version":3,"file":"StdioTransportStrategy.js","sourceRoot":"","sources":["../../src/transports/StdioTransportStrategy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AACtC,OAAO,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAI/D;;;GAGG;AACH,MAAM,OAAO,sBAAsB;IAChB,MAAM,CAAY;IAEnC;;;;;OAKG;IACH,YAAY,UAAkB,EAAE,aAAqB,EAAE,YAAgC;QACrF,IAAI,CAAC,MAAM,GAAG,IAAI,SAAS,CAAC;YAC1B,IAAI,EAAE,UAAU;YAChB,OAAO,EAAE,aAAa;SACvB,CAAC,CAAC;QACH,qBAAqB,CAAC,IAAI,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IACnD,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,OAAO;QACX,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;QAC7C,MAAM,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QACrC,MAAM,CAAC,IAAI,CAAC,0CAA0C,CAAC,CAAC;IAC1D,CAAC;IAED;;OAEG;IACH,OAAO;QACL,OAAO,OAAO,CAAC;IACjB,CAAC;IAED;;OAEG;IACH,SAAS;QACP,OAAO,IAAI,CAAC,MAAM,CAAC;IACrB,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,KAAK;QACT,MAAM,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;IAC5B,CAAC;CACF"}
|
package/dist/types.d.ts
CHANGED
|
@@ -3,7 +3,17 @@ export declare const StockQuoteSchema: z.ZodObject<{
|
|
|
3
3
|
ticker: z.ZodString;
|
|
4
4
|
fields: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
5
5
|
}, z.core.$strip>;
|
|
6
|
+
export declare const StockSearchSchema: z.ZodObject<{
|
|
7
|
+
query: z.ZodString;
|
|
8
|
+
}, z.core.$strip>;
|
|
9
|
+
export declare const HistoricalDataSchema: z.ZodObject<{
|
|
10
|
+
ticker: z.ZodString;
|
|
11
|
+
fromDate: z.ZodString;
|
|
12
|
+
toDate: z.ZodString;
|
|
13
|
+
}, z.core.$strip>;
|
|
6
14
|
export type StockQuoteInput = z.infer<typeof StockQuoteSchema>;
|
|
15
|
+
export type StockSearchInput = z.infer<typeof StockSearchSchema>;
|
|
16
|
+
export type HistoricalDataInput = z.infer<typeof HistoricalDataSchema>;
|
|
7
17
|
export interface StockQuoteResponse {
|
|
8
18
|
symbol: string;
|
|
9
19
|
name?: string;
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,eAAO,MAAM,gBAAgB;;;iBAQ3B,CAAC;AAGH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/dist/types.js
CHANGED
|
@@ -9,4 +9,20 @@ export const StockQuoteSchema = z.object({
|
|
|
9
9
|
.describe('Stock ticker symbol (e.g., AAPL, GOOGL, MSFT)'),
|
|
10
10
|
fields: z.array(z.string()).optional().describe('Optional list of specific fields to return'),
|
|
11
11
|
});
|
|
12
|
+
// Schema for stock search tool input
|
|
13
|
+
export const StockSearchSchema = z.object({
|
|
14
|
+
query: z.string().min(1).describe('Search query (company name or ticker)'),
|
|
15
|
+
});
|
|
16
|
+
// Schema for historical data tool input
|
|
17
|
+
export const HistoricalDataSchema = z.object({
|
|
18
|
+
ticker: z.string().min(1).max(10).toUpperCase().describe('Stock ticker symbol (e.g., AAPL)'),
|
|
19
|
+
fromDate: z
|
|
20
|
+
.string()
|
|
21
|
+
.regex(/^\d{4}-\d{2}-\d{2}$/)
|
|
22
|
+
.describe('Start date in YYYY-MM-DD format'),
|
|
23
|
+
toDate: z
|
|
24
|
+
.string()
|
|
25
|
+
.regex(/^\d{4}-\d{2}-\d{2}$/)
|
|
26
|
+
.describe('End date in YYYY-MM-DD format'),
|
|
27
|
+
});
|
|
12
28
|
//# sourceMappingURL=types.js.map
|
package/dist/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,oCAAoC;AACpC,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,CAAC,MAAM,CAAC;IACvC,MAAM,EAAE,CAAC;SACN,MAAM,EAAE;SACR,GAAG,CAAC,CAAC,CAAC;SACN,GAAG,CAAC,EAAE,CAAC;SACP,WAAW,EAAE;SACb,QAAQ,CAAC,+CAA+C,CAAC;IAC5D,MAAM,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,4CAA4C,CAAC;CAC9F,CAAC,CAAC"}
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,oCAAoC;AACpC,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,CAAC,MAAM,CAAC;IACvC,MAAM,EAAE,CAAC;SACN,MAAM,EAAE;SACR,GAAG,CAAC,CAAC,CAAC;SACN,GAAG,CAAC,EAAE,CAAC;SACP,WAAW,EAAE;SACb,QAAQ,CAAC,+CAA+C,CAAC;IAC5D,MAAM,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,4CAA4C,CAAC;CAC9F,CAAC,CAAC;AAEH,qCAAqC;AACrC,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,CAAC,MAAM,CAAC;IACxC,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,uCAAuC,CAAC;CAC3E,CAAC,CAAC;AAEH,wCAAwC;AACxC,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC3C,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,kCAAkC,CAAC;IAC5F,QAAQ,EAAE,CAAC;SACR,MAAM,EAAE;SACR,KAAK,CAAC,qBAAqB,CAAC;SAC5B,QAAQ,CAAC,iCAAiC,CAAC;IAC9C,MAAM,EAAE,CAAC;SACN,MAAM,EAAE;SACR,KAAK,CAAC,qBAAqB,CAAC;SAC5B,QAAQ,CAAC,+BAA+B,CAAC;CAC7C,CAAC,CAAC"}
|
|
@@ -1,14 +1,21 @@
|
|
|
1
|
+
import YahooFinance from 'yahoo-finance2';
|
|
1
2
|
import type { YahooChartResponse, YahooQuote, YahooSearchResponse } from './types.js';
|
|
3
|
+
type QuoteOptions = Parameters<InstanceType<typeof YahooFinance>['quote']>[1];
|
|
4
|
+
type SearchOptions = Parameters<InstanceType<typeof YahooFinance>['search']>[1];
|
|
5
|
+
type SearchModuleOptions = Parameters<InstanceType<typeof YahooFinance>['search']>[2];
|
|
6
|
+
type ChartOptions = Parameters<InstanceType<typeof YahooFinance>['chart']>[1];
|
|
7
|
+
type ChartModuleOptions = Parameters<InstanceType<typeof YahooFinance>['chart']>[2];
|
|
2
8
|
export interface YahooClient {
|
|
3
|
-
quote(symbol: string, options?:
|
|
4
|
-
search(query: string, options?:
|
|
5
|
-
chart(symbol: string, options
|
|
9
|
+
quote(symbol: string, options?: QuoteOptions): Promise<YahooQuote | YahooQuote[]>;
|
|
10
|
+
search(query: string, options?: SearchOptions, moduleOptions?: SearchModuleOptions): Promise<YahooSearchResponse>;
|
|
11
|
+
chart(symbol: string, options: ChartOptions, moduleOptions?: ChartModuleOptions): Promise<YahooChartResponse>;
|
|
6
12
|
}
|
|
7
13
|
export declare class YahooFinanceClient implements YahooClient {
|
|
8
|
-
private client;
|
|
9
|
-
constructor(client?:
|
|
10
|
-
quote(symbol: string, options?:
|
|
11
|
-
search(query: string, options?:
|
|
12
|
-
chart(symbol: string, options
|
|
14
|
+
private readonly client;
|
|
15
|
+
constructor(client?: InstanceType<typeof YahooFinance>);
|
|
16
|
+
quote(symbol: string, options?: QuoteOptions): Promise<YahooQuote | YahooQuote[]>;
|
|
17
|
+
search(query: string, options?: SearchOptions, moduleOptions?: SearchModuleOptions): Promise<YahooSearchResponse>;
|
|
18
|
+
chart(symbol: string, options: ChartOptions, moduleOptions?: ChartModuleOptions): Promise<YahooChartResponse>;
|
|
13
19
|
}
|
|
20
|
+
export {};
|
|
14
21
|
//# sourceMappingURL=yahooFinanceClient.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"yahooFinanceClient.d.ts","sourceRoot":"","sources":["../src/yahooFinanceClient.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"yahooFinanceClient.d.ts","sourceRoot":"","sources":["../src/yahooFinanceClient.ts"],"names":[],"mappings":"AAAA,OAAO,YAAY,MAAM,gBAAgB,CAAC;AAC1C,OAAO,KAAK,EAAE,kBAAkB,EAAE,UAAU,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAEtF,KAAK,YAAY,GAAG,UAAU,CAAC,YAAY,CAAC,OAAO,YAAY,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC9E,KAAK,aAAa,GAAG,UAAU,CAAC,YAAY,CAAC,OAAO,YAAY,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAChF,KAAK,mBAAmB,GAAG,UAAU,CAAC,YAAY,CAAC,OAAO,YAAY,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACtF,KAAK,YAAY,GAAG,UAAU,CAAC,YAAY,CAAC,OAAO,YAAY,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC9E,KAAK,kBAAkB,GAAG,UAAU,CAAC,YAAY,CAAC,OAAO,YAAY,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAEpF,MAAM,WAAW,WAAW;IAC1B,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,UAAU,GAAG,UAAU,EAAE,CAAC,CAAC;IAClF,MAAM,CACJ,KAAK,EAAE,MAAM,EACb,OAAO,CAAC,EAAE,aAAa,EACvB,aAAa,CAAC,EAAE,mBAAmB,GAClC,OAAO,CAAC,mBAAmB,CAAC,CAAC;IAChC,KAAK,CACH,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,YAAY,EACrB,aAAa,CAAC,EAAE,kBAAkB,GACjC,OAAO,CAAC,kBAAkB,CAAC,CAAC;CAChC;AAED,qBAAa,kBAAmB,YAAW,WAAW;IACpD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAoC;gBAE/C,MAAM,CAAC,EAAE,YAAY,CAAC,OAAO,YAAY,CAAC;IAIhD,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,UAAU,GAAG,UAAU,EAAE,CAAC;IAKjF,MAAM,CACV,KAAK,EAAE,MAAM,EACb,OAAO,CAAC,EAAE,aAAa,EACvB,aAAa,CAAC,EAAE,mBAAmB,GAClC,OAAO,CAAC,mBAAmB,CAAC;IAKzB,KAAK,CACT,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,YAAY,EACrB,aAAa,CAAC,EAAE,kBAAkB,GACjC,OAAO,CAAC,kBAAkB,CAAC;CAI/B"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"yahooFinanceClient.js","sourceRoot":"","sources":["../src/yahooFinanceClient.ts"],"names":[],"mappings":"AAAA,OAAO,YAAY,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"yahooFinanceClient.js","sourceRoot":"","sources":["../src/yahooFinanceClient.ts"],"names":[],"mappings":"AAAA,OAAO,YAAY,MAAM,gBAAgB,CAAC;AAuB1C,MAAM,OAAO,kBAAkB;IACZ,MAAM,CAAoC;IAE3D,YAAY,MAA0C;QACpD,IAAI,CAAC,MAAM,GAAG,MAAM,IAAI,IAAI,YAAY,EAAE,CAAC;IAC7C,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,MAAc,EAAE,OAAsB;QAChD,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QACxD,OAAO,MAAmC,CAAC;IAC7C,CAAC;IAED,KAAK,CAAC,MAAM,CACV,KAAa,EACb,OAAuB,EACvB,aAAmC;QAEnC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,aAAa,CAAC,CAAC;QACvE,OAAO,MAA6B,CAAC;IACvC,CAAC;IAED,KAAK,CAAC,KAAK,CACT,MAAc,EACd,OAAqB,EACrB,aAAkC;QAElC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE,aAAa,CAAC,CAAC;QACvE,OAAO,MAA4B,CAAC;IACtC,CAAC;CACF"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "stockquotes-mcp",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.5",
|
|
4
4
|
"description": "MCP Server for fetching stock quotes from Yahoo Finance",
|
|
5
5
|
"author": "Lionel Schiepers <lionel_schiepers@hotmail.com>",
|
|
6
6
|
"license": "MIT",
|
|
@@ -57,14 +57,25 @@
|
|
|
57
57
|
"@modelcontextprotocol/sdk": "^1.25.2",
|
|
58
58
|
"date-fns": "^4.1.0",
|
|
59
59
|
"express": "^5.2.1",
|
|
60
|
+
"express-rate-limit": "^8.2.1",
|
|
61
|
+
"helmet": "^8.1.0",
|
|
62
|
+
"node-cache": "^5.1.2",
|
|
63
|
+
"winston": "^3.19.0",
|
|
60
64
|
"yahoo-finance2": "^3.11.2",
|
|
61
65
|
"zod": "^4.3.5"
|
|
62
66
|
},
|
|
63
67
|
"devDependencies": {
|
|
68
|
+
"@semantic-release/changelog": "^6.0.3",
|
|
69
|
+
"@semantic-release/commit-analyzer": "^13.0.1",
|
|
70
|
+
"@semantic-release/git": "^10.0.1",
|
|
71
|
+
"@semantic-release/github": "^12.0.2",
|
|
72
|
+
"@semantic-release/npm": "^13.1.3",
|
|
73
|
+
"@semantic-release/release-notes-generator": "^14.1.0",
|
|
64
74
|
"@types/express": "^5.0.6",
|
|
65
75
|
"@types/jest": "^30.0.0",
|
|
66
|
-
"@types/node": "^25.0.
|
|
76
|
+
"@types/node": "^25.0.9",
|
|
67
77
|
"@types/supertest": "^6.0.3",
|
|
78
|
+
"@types/winston": "^2.4.4",
|
|
68
79
|
"@typescript-eslint/eslint-plugin": "^8.53.0",
|
|
69
80
|
"@typescript-eslint/parser": "^8.53.0",
|
|
70
81
|
"eslint": "^9.39.2",
|
|
@@ -72,7 +83,8 @@
|
|
|
72
83
|
"husky": "^9.1.7",
|
|
73
84
|
"jest": "^30.2.0",
|
|
74
85
|
"npm-check-updates": "^19.3.1",
|
|
75
|
-
"prettier": "^3.
|
|
86
|
+
"prettier": "^3.8.0",
|
|
87
|
+
"semantic-release": "^25.0.2",
|
|
76
88
|
"supertest": "^7.2.2",
|
|
77
89
|
"ts-jest": "^29.4.6",
|
|
78
90
|
"tsx": "^4.21.0",
|