feat(mcp): add Codex session support - #949
Conversation
📝 WalkthroughWalkthroughAdds Codex session reporting and parsing, registers a new ChangesMCP server and CLI updates
Sequence Diagram(s)sequenceDiagram
autonumber
participant Client as Client
participant MCP as MCP Server
participant CLI as Codex CLI
participant FS as Filesystem
Client->>MCP: Request `codex-session`
MCP->>MCP: validate args (codexParametersSchema)
MCP->>CLI: runCodexCliJson('session', parameters)
CLI->>FS: read ${CODEX_HOME:-~/.codex}/sessions/
FS-->>CLI: session JSON
CLI-->>MCP: stdout (raw JSON)
MCP->>MCP: parseCodexResponse(raw, codexSessionResponseSchema)
MCP-->>Client: JSON result (pretty-printed)
Estimated code review effort🎯 4 (Complex) | ⏱️ ~50 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Tip 💬 Introducing Slack Agent: The best way for teams to turn conversations into code.Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.
Built for teams:
One agent for your entire SDLC. Right inside Slack. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
Validation update:
Note: the first Nix-shell test run hit cold-start timeout noise while the shell and caches were still warming up, but a clean rerun passed fully. |
There was a problem hiding this comment.
Actionable comments posted: 4
🧹 Nitpick comments (4)
apps/mcp/src/cli-utils.ts (1)
16-18: KeeppathExistsinternal.The helper only needs to support
resolveBunExecutable(); the current test spy can be removed because the Bun-runtime branch returns before filesystem lookup.♻️ Proposed cleanup
-export function pathExists(candidate: string): boolean { +function pathExists(candidate: string): boolean { return fs.existsSync(candidate); }Also remove the redundant test spy:
- vi.spyOn(cliUtils, 'pathExists').mockReturnValue(false);As per coding guidelines, “Only export constants, functions, and types that are actually used by other modules - do not export internal/private constants used only within the same file”.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/mcp/src/cli-utils.ts` around lines 16 - 18, The function pathExists is exported but only used internally by resolveBunExecutable, so remove the export to make it file-private (rename/export removal for pathExists) and update any internal references to the now-internal function; also remove the redundant test spy that was targeting pathExists since the Bun-runtime branch returns before filesystem lookup and the spy is unnecessary. Ensure resolveBunExecutable still calls the (now non-exported) pathExists and adjust imports/usages elsewhere if any were relying on the export.apps/mcp/src/cli-utils.test.ts (1)
1-4: Move this coverage into an in-source Vitest block.This new standalone
*.test.tsfile conflicts with the repo’s in-source testing convention; move the tests intoapps/mcp/src/cli-utils.tsunderif (import.meta.vitest != null).As per coding guidelines, “
**/**.test.ts: Use in-source testing withif (import.meta.vitest != null)blocks instead of separate test files”.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/mcp/src/cli-utils.test.ts` around lines 1 - 4, Move the external test file into an in-source Vitest block inside apps/mcp/src/cli-utils.ts by copying the tests from apps/mcp/src/cli-utils.test.ts into a new if (import.meta.vitest != null) { ... } section in cli-utils.ts; update references to createFixture and any imports so they are scoped inside that block, remove the standalone .test.ts file, and ensure the tests import CLI functions directly from the same module (e.g., functions exported by cli-utils.ts) so the in-source tests run under import.meta.vitest.apps/mcp/src/codex.ts (1)
141-144: Wrap JSON parsing operations with Result.try() for all three Codex functions.Lines 131-144 use raw
JSON.parse()without error handling ingetCodexDaily,getCodexMonthly, andgetCodexSession. Per the coding guidelines and established patterns elsewhere in the codebase, wrap these JSON parsing operations withResult.try(). Consider creating a shared Codex JSON parse helper to avoid duplication across the three functions.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/mcp/src/codex.ts` around lines 141 - 144, The three functions getCodexDaily, getCodexMonthly, and getCodexSession call runCodexCliJson(...) and then use raw JSON.parse(...) directly; change these to use Result.try() around the parse+schema.parse step to capture parse errors (e.g. Result.try(() => schema.parse(JSON.parse(raw)))) and return/propagate the Result. To avoid duplication, add a small helper like parseCodexResponse(raw, schema) that performs Result.try(() => schema.parse(JSON.parse(raw))) and use it from getCodexDaily (codexDailyResponseSchema), getCodexMonthly (codexMonthlyResponseSchema) and getCodexSession (codexSessionResponseSchema), keeping runCodexCliJson usage unchanged.apps/mcp/src/mcp.ts (1)
253-256: Add tool-call assertions to verify empty claudePath behavior.The test only validates server construction. Since
claudePath: ''causes fallback to default Claude paths, add assertions that call thedailyorsessiontool to verify the tools respond correctly when no data is available. This ensures the MCP server tools handle the empty path scenario end-to-end.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/mcp/src/mcp.ts` around lines 253 - 256, The test for createMcpServer with claudePath:'' only checks construction; extend it to exercise the MCP tools end-to-end by invoking one or both tools (e.g., the 'daily' and/or 'session' tool handlers exposed by the created server) and asserting their responses when no data exists; locate the test that calls createMcpServer, retrieve the server.tools (or the exported tool call functions) and perform a tool invocation (e.g., call daily/session with an appropriate empty or minimal request) and assert the expected fallback behavior (error/empty result/default message) to verify empty claudePath handling.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@apps/mcp/README.md`:
- Line 66: Update the README sentence that references CODEX_HOME to explicitly
state that session files live in the sessions/ subdirectory and show the
resolved default; replace the current line with wording like: "Codex session
usage must be read from ${CODEX_HOME:-~/.codex}/sessions/, with CODEX_HOME
resolved and defaulting to ~/.codex" so it mentions the sessions/ directory and
the resolved default for CODEX_HOME.
In `@apps/mcp/src/cli-utils.ts`:
- Around line 20-40: resolveBunExecutable currently only checks for "bun" and
probes node_modules/.bin/bun, which misses Windows variants; update
resolveBunExecutable to consider platform-specific executable names (e.g., on
Windows check "bun.exe" and "bun.cmd" in addition to "bun"), expand the probe
loop that builds candidate paths (the variable candidate) to test each name
variant using pathExists, and when inspecting process.execPath (used in the
currentExecutable check) compare its basename against the same set of variants
so installed shims are detected; ensure the function still returns the first
existing candidate or falls back to 'bun' if none are found.
In `@apps/mcp/src/command.ts`:
- Around line 103-110: The header suppression currently only triggers for
explicit '--type' / '-t' with the next token 'stdio'; change the logic so
renderHeader is also suppressed when stdio is provided as a single-token flag
(e.g. '--type=stdio' or '-t=stdio') and when no type flag is provided (default
stdio). Update the computation around stdioIndex/args used before calling cli
(the variables stdioIndex, args, and the renderHeader option passed to
cli/mcpCommand) to treat any of these cases as stdio: (1) existing '--type' or
'-t' followed by 'stdio', (2) '--type=stdio' or '-t=stdio' tokens, or (3)
absence of any '--type'/'-t' flag (no type specified) — then set suppressHeader
true so renderHeader becomes null.
In `@apps/mcp/src/mcp-utils.ts`:
- Around line 5-9: Replace the try/catch in defaultOptions with the
`@praha/byethrow` Result pattern: call Result.try({ try: () => getClaudePaths(),
catch: (err) => err })(), then use Result.isFailure(result) to detect errors and
return { claudePath: '' } as const satisfies LoadOptions on failure; otherwise
use result.value[0] ?? '' to build and return the LoadOptions object; reference
getClaudePaths(), defaultOptions(), Result.try and Result.isFailure when
applying the change.
---
Nitpick comments:
In `@apps/mcp/src/cli-utils.test.ts`:
- Around line 1-4: Move the external test file into an in-source Vitest block
inside apps/mcp/src/cli-utils.ts by copying the tests from
apps/mcp/src/cli-utils.test.ts into a new if (import.meta.vitest != null) { ...
} section in cli-utils.ts; update references to createFixture and any imports so
they are scoped inside that block, remove the standalone .test.ts file, and
ensure the tests import CLI functions directly from the same module (e.g.,
functions exported by cli-utils.ts) so the in-source tests run under
import.meta.vitest.
In `@apps/mcp/src/cli-utils.ts`:
- Around line 16-18: The function pathExists is exported but only used
internally by resolveBunExecutable, so remove the export to make it file-private
(rename/export removal for pathExists) and update any internal references to the
now-internal function; also remove the redundant test spy that was targeting
pathExists since the Bun-runtime branch returns before filesystem lookup and the
spy is unnecessary. Ensure resolveBunExecutable still calls the (now
non-exported) pathExists and adjust imports/usages elsewhere if any were relying
on the export.
In `@apps/mcp/src/codex.ts`:
- Around line 141-144: The three functions getCodexDaily, getCodexMonthly, and
getCodexSession call runCodexCliJson(...) and then use raw JSON.parse(...)
directly; change these to use Result.try() around the parse+schema.parse step to
capture parse errors (e.g. Result.try(() => schema.parse(JSON.parse(raw)))) and
return/propagate the Result. To avoid duplication, add a small helper like
parseCodexResponse(raw, schema) that performs Result.try(() =>
schema.parse(JSON.parse(raw))) and use it from getCodexDaily
(codexDailyResponseSchema), getCodexMonthly (codexMonthlyResponseSchema) and
getCodexSession (codexSessionResponseSchema), keeping runCodexCliJson usage
unchanged.
In `@apps/mcp/src/mcp.ts`:
- Around line 253-256: The test for createMcpServer with claudePath:'' only
checks construction; extend it to exercise the MCP tools end-to-end by invoking
one or both tools (e.g., the 'daily' and/or 'session' tool handlers exposed by
the created server) and asserting their responses when no data exists; locate
the test that calls createMcpServer, retrieve the server.tools (or the exported
tool call functions) and perform a tool invocation (e.g., call daily/session
with an appropriate empty or minimal request) and assert the expected fallback
behavior (error/empty result/default message) to verify empty claudePath
handling.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: aa323263-d3ce-4424-af0f-4ca36ff08554
📒 Files selected for processing (7)
apps/mcp/README.mdapps/mcp/src/cli-utils.test.tsapps/mcp/src/cli-utils.tsapps/mcp/src/codex.tsapps/mcp/src/command.tsapps/mcp/src/mcp-utils.tsapps/mcp/src/mcp.ts
2ea9a0a to
d470999
Compare
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub.
|
d470999 to
9f87fdf
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@apps/mcp/README.md`:
- Line 88: The img tag for the sponsors badge lacks an alt attribute; update the
<img> element (the sponsors SVG included in README.md) to include a concise,
descriptive alt text (e.g., "Project sponsors" or "Sponsors logos") so screen
readers can convey the image purpose and improve accessibility.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 6b54122f-93c7-4e93-b049-946a3aeb4552
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (7)
apps/mcp/README.mdapps/mcp/package.jsonapps/mcp/src/cli-utils.tsapps/mcp/src/codex.tsapps/mcp/src/command.tsapps/mcp/src/mcp-utils.tsapps/mcp/src/mcp.ts
✅ Files skipped from review due to trivial changes (1)
- apps/mcp/package.json
🚧 Files skipped from review as they are similar to previous changes (5)
- apps/mcp/src/mcp-utils.ts
- apps/mcp/src/codex.ts
- apps/mcp/src/cli-utils.ts
- apps/mcp/src/command.ts
- apps/mcp/src/mcp.ts
|
|
||
| <p align="center"> | ||
| <a href="https://github.com/sponsors/ryoppippi"> | ||
| <img src="https://cdn.jsdelivr.net/gh/ryoppippi/sponsors@main/sponsors.svg"> |
There was a problem hiding this comment.
Add alt text for accessibility.
The sponsors image is missing an alt attribute, which prevents screen reader users from understanding the image's purpose.
♿ Proposed fix
- <img src="https://cdn.jsdelivr.net/gh/ryoppippi/sponsors@main/sponsors.svg">
+ <img src="https://cdn.jsdelivr.net/gh/ryoppippi/sponsors@main/sponsors.svg" alt="GitHub Sponsors">🧰 Tools
🪛 markdownlint-cli2 (0.22.1)
[warning] 88-88: Images should have alternate text (alt text)
(MD045, no-alt-text)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@apps/mcp/README.md` at line 88, The img tag for the sponsors badge lacks an
alt attribute; update the <img> element (the sponsors SVG included in README.md)
to include a concise, descriptive alt text (e.g., "Project sponsors" or
"Sponsors logos") so screen readers can convey the image purpose and improve
accessibility.
|
Hi @ryoppippi, when you have a moment, could you please take a look at PR #949? The latest socket pass appears to have been limited by the service, so I’m not treating that last bot comment as actionable on my side. Thanks. |
|
sorry we decided to remove mcp in the next version |
Summary
codex-sessionMCP tool so Codex session costs can be queried at session granularityWhy
The MCP package already exposed Codex daily and monthly tools, but it did not expose the underlying Codex session report. That prevented session-level Codex cost inspection through MCP even though the Codex CLI supported it.
Impact
Codex users can now inspect daily, monthly, and session-level usage through the existing
@ccusage/mcppackage without maintaining a separate MCP server.Validation
pnpm run formatpnpm typecheckpnpm run testSummary by CodeRabbit
New Features
Improvements
Documentation
Chores