Skip to content

Commit 9a5776e

Browse files
authored
Merge branch 'master' into feat/auth-session-fix
2 parents e066cae + 7bd69a6 commit 9a5776e

15 files changed

Lines changed: 215 additions & 50 deletions

.github/workflows/knip.yml

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
name: Knip
2+
3+
on:
4+
push:
5+
branches: [main, master, develop]
6+
pull_request:
7+
branches: [main, master, develop]
8+
9+
jobs:
10+
knip:
11+
runs-on: ubuntu-latest
12+
13+
steps:
14+
- name: Checkout code
15+
uses: actions/checkout@v4
16+
17+
- name: Setup Node.js
18+
uses: actions/setup-node@v4
19+
with:
20+
node-version: '20.x'
21+
cache: 'npm'
22+
23+
- name: Install dependencies
24+
run: npm ci
25+
26+
- name: Run knip
27+
run: npx -y knip@5

.github/workflows/release.yml

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@ on:
77
jobs:
88
release:
99
runs-on: ubuntu-latest
10+
permissions:
11+
contents: write
12+
issues: write
13+
pull-requests: write
14+
id-token: write
1015
steps:
1116
- uses: actions/checkout@v4
1217
with:
@@ -16,16 +21,11 @@ jobs:
1621
- name: Setup Node.js
1722
uses: actions/setup-node@v4
1823
with:
19-
node-version: '18'
24+
node-version: '20'
2025
registry-url: 'https://registry.npmjs.org'
2126

22-
- name: Configure NPM authentication
23-
run: |
24-
echo "//registry.npmjs.org/:_authToken=${NPM_TOKEN}" > ~/.npmrc
25-
npm whoami
26-
env:
27-
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
28-
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
27+
- name: Upgrade npm for trusted publishing
28+
run: npm install -g npm@latest
2929

3030
- name: Install dependencies
3131
run: npm ci
@@ -37,10 +37,13 @@ jobs:
3737
run: npm test --if-present
3838

3939
- name: Semantic Release
40+
id: semantic
4041
uses: cycjimmy/semantic-release-action@v4
4142
with:
42-
semantic_version: 22
43+
semantic_version: 24
4344
env:
4445
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
45-
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
46-
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
46+
47+
- name: Publish to npm (trusted publishing via OIDC)
48+
if: steps.semantic.outputs.new_release_published == 'true'
49+
run: npm publish --provenance --access public

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,4 +148,5 @@ ib-gateway/clientportal.gw/.vertx
148148
ib-gateway/clientportal.gw/.vertx/
149149

150150
# Docker volumes
151-
data/
151+
data/
152+
.claude/settings.local.json

.releaserc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
]
2222
}
2323
],
24-
"@semantic-release/npm",
24+
["@semantic-release/npm", { "npmPublish": false }],
2525
"@semantic-release/github"
2626
]
2727
}

README.md

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -222,4 +222,12 @@ For a complete guide on creating and customizing Flex Queries, see the [IB Flex
222222

223223
## License
224224

225-
MIT License - see LICENSE file for details.
225+
MIT License - see LICENSE file for details.
226+
227+
## Thanks to our contributors
228+
229+
A big thank you to everyone who has contributed to making this project better.
230+
231+
<a href="https://github.com/code-rabi/interactive-brokers-mcp/graphs/contributors">
232+
<img src="https://contrib.rocks/image?repo=code-rabi/interactive-brokers-mcp" alt="Contributors" />
233+
</a>

knip.json

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"$schema": "https://unpkg.com/knip@5/schema.json",
3+
"ignore": ["ib-gateway/**"],
4+
"ignoreDependencies": [
5+
"@semantic-release/commit-analyzer",
6+
"@semantic-release/github",
7+
"@semantic-release/npm",
8+
"@semantic-release/release-notes-generator",
9+
"conventional-changelog-conventionalcommits",
10+
"semantic-release"
11+
]
12+
}

package-lock.json

Lines changed: 0 additions & 13 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,14 @@
3939
],
4040
"author": "Nitay Rabinovich",
4141
"license": "MIT",
42+
"repository": {
43+
"type": "git",
44+
"url": "git+https://github.com/code-rabi/interactive-brokers-mcp.git"
45+
},
46+
"bugs": {
47+
"url": "https://github.com/code-rabi/interactive-brokers-mcp/issues"
48+
},
49+
"homepage": "https://github.com/code-rabi/interactive-brokers-mcp#readme",
4250
"dependencies": {
4351
"@modelcontextprotocol/sdk": "^1.17.2",
4452
"axios": "^1.6.0",

src/flex-query-client.ts

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,18 @@ import axios, { AxiosInstance } from "axios";
22
import { Logger } from "./logger.js";
33
import { parseStringPromise } from "xml2js";
44

5-
export interface FlexQueryClientConfig {
5+
interface FlexQueryClientConfig {
66
token: string;
77
}
88

9-
export interface FlexQueryResponse {
9+
interface FlexQueryResponse {
1010
referenceCode?: string;
1111
url?: string;
1212
error?: string;
1313
errorCode?: string;
1414
}
1515

16-
export interface FlexStatementResponse {
16+
interface FlexStatementResponse {
1717
data?: string; // XML data
1818
error?: string;
1919
errorCode?: string;
@@ -24,6 +24,21 @@ export interface FlexStatementResponse {
2424
* API Documentation: https://www.interactivebrokers.com/en/software/am/am/reports/flex_web_service_version_3.htm
2525
*/
2626
export class FlexQueryClient {
27+
// IB Flex Web Service error codes that mean "try again shortly" — the statement
28+
// is being prepared. All other Fail codes are terminal (bad token, invalid query, etc.).
29+
private static readonly TRANSIENT_GET_STATEMENT_ERROR_CODES = new Set([
30+
"1001", // Statement could not be generated at this time
31+
"1004", // Statement is incomplete at this time
32+
"1005", // Settlement data is not ready
33+
"1006", // FIFO P/L data is not ready
34+
"1007", // MTM P/L data is not ready
35+
"1008", // MTM and FIFO P/L data is not ready
36+
"1009", // Server is under heavy load
37+
"1018", // Too many requests from this token
38+
"1019", // Statement generation in progress
39+
"1021", // Statement could not be retrieved at this time
40+
]);
41+
2742
private client: AxiosInstance;
2843
private token: string;
2944
// Fixed: gdcdyn → ndcdyn, /Universal/servlet → /AccountManagement/FlexWebService
@@ -182,16 +197,21 @@ export class FlexQueryClient {
182197
const statementResponse = await this.getStatement(sendResponse.referenceCode);
183198

184199
if (statementResponse.error) {
185-
// Check if it's a "not ready yet" error
186-
if (
187-
statementResponse.errorCode === "1019" || // Statement generation in progress
188-
statementResponse.error.includes("in progress") ||
189-
statementResponse.error.includes("not ready")
190-
) {
191-
Logger.log(`[FLEX-QUERY] Statement not ready yet, retrying...`);
200+
const code = statementResponse.errorCode ?? "";
201+
const normalizedError = statementResponse.error.toLowerCase();
202+
const isTransient =
203+
FlexQueryClient.TRANSIENT_GET_STATEMENT_ERROR_CODES.has(code) ||
204+
normalizedError.includes("in progress") ||
205+
normalizedError.includes("not ready") ||
206+
normalizedError.includes("try again");
207+
208+
if (isTransient) {
209+
Logger.log(
210+
`[FLEX-QUERY] Statement not ready yet (code ${code || "?"}: ${statementResponse.error}), retrying...`
211+
);
192212
continue;
193213
}
194-
214+
195215
// It's a real error
196216
return statementResponse;
197217
}
@@ -226,4 +246,3 @@ export class FlexQueryClient {
226246
}
227247

228248

229-

src/flex-query-storage.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ export interface SavedFlexQuery {
1212
lastUsed?: string;
1313
}
1414

15-
export interface FlexQueriesStore {
15+
interface FlexQueriesStore {
1616
queries: SavedFlexQuery[];
1717
}
1818

0 commit comments

Comments
 (0)