Skip to content

docs(mcp): READMEs say where Fortran unit 6 output goes under the fd isolation - #264

Merged
k-yoshimi merged 1 commit into
developfrom
docs/mcp-readme-fd-isolation
Oct 17, 2026
Merged

k-yoshimi merged 1 commit into
developfrom
docs/mcp-readme-fd-isolation

Conversation

@k-yoshimi

Copy link
Copy Markdown
Owner

Docs-only follow-up to #257 / #263, from the ai-review-cycle docs pass on #263.

What

  • tr_mcp / tot_mcp / ti_mcp / wr_mcp / wrx_mcp README, FAQ 「ログはどこで確認できますか」: a paragraph saying that the library's WRITE(6,...) (unit 6 = fd 1) lands on stderr because main() hands fd 1 to stderr through python/_fd_isolation.py immediately before the server is built; that a merged stdout/stderr (a terminal, 2>&1) discards it with one warning line on stderr; that the same-file test is by fstat inode, so a Windows pipe/console is not recognised and fd 1 goes to stderr as usual; and how to keep the output (2>server.log).
  • eq_mcp README: a new ## Logs section with the same content in English (that README has no FAQ).

No code, CHANGELOG untouched.

Review

In-house + Codex on the first draft (one MED: the Windows qualification; one LOW: 「起動直後」→「サーバ構築の直前」), both applied; both reviewers confirmed the delta; ai-review-cycle Antigravity docs pass had no findings.

🤖 Generated with Claude Code

https://claude.ai/code/session_01TA2KahTs3qLMZL6yjSsWwT

…isolation

The logging FAQ of tr / tot / ti / wr / wrx_mcp (and a new Logs section
of eq_mcp's README) now say that the library's WRITE(6,...) lands on
stderr because main() redirects fd 1 (#257 / #263), that a merged
stdout/stderr (a terminal, 2>&1) discards it with one warning line, and
how to keep it (2>server.log). Suggested by the docs review of #263.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TA2KahTs3qLMZL6yjSsWwT
@k-yoshimi
k-yoshimi merged commit 963ae3d into develop Oct 17, 2026
3 checks passed
HengyuLi-Ozaki-lab added a commit to HengyuLi-Ozaki-lab/task that referenced this pull request Oct 18, 2026
develop gained k-yoshimi#256, k-yoshimi#257, k-yoshimi#258, k-yoshimi#259, k-yoshimi#261, k-yoshimi#263 and k-yoshimi#264 since the
last merge (f41fe5b).

Two conflicts:
- CHANGELOG.md: this branch's entry and develop's new entries were
  added at the same place under "### Added"; both kept.
- fp/fp_api.f90, the USE lists of the module: this branch reads NTG1,
  TVOLR and the six P*T arrays from fpcomm, k-yoshimi#259 imports
  fp_param_generation; both kept.

And one change that no line conflict shows. k-yoshimi#259 replaced the clear of
g_prepared in fp_api_set_param by a count of registry sets
(fp_param_generation, compared by fp_run with g_prep_generation). The
global scalars of fp_get_state were gated on g_prepared alone, so after
the merge a set no longer zeroed them, against what this branch
documents and tests ("zero ... and again after a set_param until the
next run that is made"). The gate is now "prepared, and no set since
the last prep" (g_prepared .AND. g_prep_generation ==
fp_param_generation()), which also covers sets through tot's "fp:"
dispatcher.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
HengyuLi-Ozaki-lab added a commit to HengyuLi-Ozaki-lab/task that referenced this pull request Oct 18, 2026
develop gained k-yoshimi#242, k-yoshimi#243, k-yoshimi#248, k-yoshimi#249, k-yoshimi#251, k-yoshimi#254, k-yoshimi#255, k-yoshimi#256, k-yoshimi#257,
k-yoshimi#258, k-yoshimi#259, k-yoshimi#261, k-yoshimi#263 and k-yoshimi#264 since this branch left it.

One conflict, in python/eqlib/_ffi.py, python/fplib/_ffi.py and
python/trlib/_ffi.py alike: the end of load_library. k-yoshimi#261 (k-yoshimi#246) checks
the state layout of the library just loaded and raises
<Mod>libAbiError on a mismatch; this branch closes the directory it
registered with os.add_dll_directory when the load fails. The check is
now inside the block that cleans up, so a library refused for its
layout does not leave its directory in the process-wide DLL search set
either (or an entry in _DLL_DIR_HANDLES). Order as on develop: the
layout check, then the prototypes.

With the check on the load path, the cases of test_platform_libname.py
that fake the loaded library (ctypes.CDLL patched) were refused by it:
24 of 39 failed. Each of the three files now has an autouse fixture that
patches check_state_layout out for them (the check has its own cases in
test_ffi.py, TestLibraryLayout), and one new case per module puts a
check back that raises AbiMismatchError (with the prototypes passing,
so that only the check can refuse the load) and asserts
<Mod>libAbiError, the directory handle closed and nothing registered;
with the check moved after the cleanup block, that case fails (measured
on eq).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
HengyuLi-Ozaki-lab added a commit to HengyuLi-Ozaki-lab/task that referenced this pull request Oct 18, 2026
As said on k-yoshimi#257: with the shared module in develop, fp_mcp drops its
own copy of the isolation and does what the other six servers do since
k-yoshimi#257 and k-yoshimi#263. main() calls _fd_isolation.install() immediately before
the stdio server is built (after the --help / --print-tools /
missing-SDK returns); the module is imported after the library wrapper,
whose directory it shares. fp_mcp/server.py now differs from develop by
that import, that call and the docstring section, which keeps the FP
measurement (FPWRTPRF writes the radial profile table at preparation
and every NTG2STEP steps, every step by default).
So fp_mcp also gets what the module handles beyond the plain redirect:
fd 2 closed, stdout and stderr the same file, one flag per process.

Tests: fp_mcp/tests/test_fd_isolation.py runs the shared checks
(python/mcp-servers/fd_isolation_cases.py), and
python/tests/test_fd_isolation.py lists fp_mcp among the servers whose
test file must call every shared case. fp_mcp/tests/test_import_isolation.py
is removed: its five cases (import leaves fd 1 and sys.stdout alone,
main() installs before the server starts, installing twice, --help and
--print-tools, the missing SDK) are among the shared ones or the
module's own. README Q8 says where unit 6 output goes, as k-yoshimi#264 did for
the other servers; a CHANGELOG entry.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
HengyuLi-Ozaki-lab added a commit to HengyuLi-Ozaki-lab/task that referenced this pull request Oct 21, 2026
develop now carries the pieces split out of this branch (k-yoshimi#256 eq_save,
k-yoshimi#257 the MCP fd isolation, k-yoshimi#265 the mcp pin) and k-yoshimi#232, k-yoshimi#233, k-yoshimi#240, k-yoshimi#242,
k-yoshimi#243, k-yoshimi#248, k-yoshimi#249, k-yoshimi#251, k-yoshimi#254, k-yoshimi#255, k-yoshimi#258, k-yoshimi#259, k-yoshimi#261, k-yoshimi#263, k-yoshimi#264. 43
files conflicted; each was resolved as follows.

- Taken from develop (36 files): every file where this branch only
  changed the mcp pin to "mcp>=0.9,<2" (develop has ">=1.2,<2", k-yoshimi#265):
  the seven pyproject.toml, six READMEs, the fp, ti, tot, wr and wrx
  servers, the Sphinx MCP pages, the trlib presentation and its
  builder, the 2026-04-18 MCP plan; and the eq_save pieces now in
  develop in their reviewed form: eq/eq_api.f90, eq/eq_api.h,
  python/eqlib/tests/test_save.py, eq_mcp/tests/test_save_tool.py; and
  tr_mcp/server.py, whose changes here were this branch's own fd
  isolation (develop's _fd_isolation replaces it) and the os._exit(0)
  at the end of main().
- The os._exit(0) that ended main() of tr_mcp and eq_mcp on this branch
  (to skip the Python teardown, cited in k-yoshimi#227 item 5) is gone with
  them: develop's main() returns 0, as approved in k-yoshimi#257. The abort it
  avoided was a double DEALLOCATE, which this branch fixed in
  tr/trcomm.f90 (DEALLOCATE_TRCOMM returns when nothing is allocated);
  that fix stays, merged without a conflict.
- eq/eqfile.f90: develop's (EQSAVE without an argument, EQSAVE_IERR
  doing the work, and its kept EQDSKR error), plus this branch's
  MODELG=25 in EQ_READ's EQDSK branch (k-yoshimi#228-2). eq/eqmenu.f90 merged
  without a conflict but kept this branch's "CALL EQSAVE(IERR)"; it is
  develop's "CALL EQSAVE" again, as EQSAVE takes no argument.
- python/eqlib/_ffi.py, eqlib.py, tests/test_eqlib.py: develop's, plus
  this branch's get_psi_rz (the eq_common_get_psi_rz_ prototype, the
  Eq.get_psi_rz method, its closed-handle assertion).
- eq_mcp/server.py: develop's (the save tool of k-yoshimi#256, the shared fd
  isolation), plus this branch's get_psi_rz handler and tool and its
  --print-tools entry (13 tools). eq_mcp/tests/test_server.py: this
  branch's (13 tools with save and get_psi_rz), which contains
  develop's change.
- python/mcp-servers/eq_mcp/tests/test_import_isolation.py (this branch
  only, no conflict) is removed: it pinned this branch's own isolation
  helper (_install_fd_isolation, _FD_ISOLATION_INSTALLED in eq_mcp and
  tr_mcp), which develop's python/_fd_isolation.py replaces; develop's
  tests/test_fd_isolation.py of each of the seven servers checks the
  same contract (an import leaves fd 1 and sys.stdout alone).
- .github/workflows/python-tests.yml: develop's mcp pin; this branch's
  numpy install (the get_psi_rz tests import numpy) and ../task symlink
  step kept.
- CHANGELOG.md did not conflict. The three k-yoshimi#228 entries this branch held
  back in d8b6e4d are added to [Unreleased] Fixed, after its first
  entry, where no other open pull request inserts.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant