Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 18 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -228,18 +228,25 @@ is specific to their host.
content blocks, then one JSON text block with `summary`, `effects`, `error` and
`structuredContent` when the call failed, returned structured content or no blocks;
`isError` on any non-success, with the remote content of an `MCP_TOOL_ERROR` preserved.
- `readProjectToolCatalog(dispatch, { backend?, environmentUid?, previous?, signal? })`:
`mcp-list` (read-only), then one `mcp-tools` per saved connection, two at a time. A
connection whose catalog cannot be read keeps its previous tools and is named in
`unavailable`; a removed connection loses them; connections outside the scope are
carried over. The session for a connection's backend is verified when its tool is called.
- `createProjectToolCatalog({ dispatch, file?, staleMs?, notify?, disabled? })`: the shared
on-disk catalog, `project-tool-catalog.json` beside `mcp-connections.json`
- `readProjectToolCatalog(dispatch, { backend?, environmentUid?, previous?, signal?, budgetMs? })`:
`mcp-list` (read-only), then one `mcp-tools` per saved connection, two at a time, all
within one budget (300 s by default). A connection whose catalog cannot be read, or is
not read before the budget runs out, keeps its previous tools and stays in the catalog
marked `unavailable` with the reason, so a scope whose connections exist is never
written empty and healthy; a removed connection loses its tools; connections outside the
scope are carried over. The session for a connection's backend is verified when its tool
is called.
- `createProjectToolCatalog({ dispatch, file?, backend?, budgetMs?, staleMs?, notify?, disabled? })`:
the shared on-disk catalog, `project-tool-catalog.json` beside `mcp-connections.json`
(`mainSequenceStateDirectory(env)` names that directory). `list()` answers from the file
at once, scoped to the current account's backend once a refresh has learned it;
`refresh()` re-reads under a lock, so one process reads catalogs at a time while the
others pick its result up from the file; `update()`, `dispose()` and `notify` serve a
long-lived host such as the Codex MCP server. The file holds schemas and labels only.
at once, for the host's backend only: the one given, or resolved by `ready()` without a
network request the way `auth-status` resolves it, or learned from a refresh; until it is
known a listing is empty, never another backend's tools. `state()` reports the connections
marked `unavailable` in the file, whichever process marked them. `refresh()` re-reads
under a lock, so one process reads catalogs at a time while the others pick its result up
from the file, and ends its dispatcher's signal when it returns; `update()`, `dispose()`
and `notify` serve a long-lived host such as the Codex MCP server. The file holds schemas
and labels only.
- The `mcp-catalog` action returns the same definitions, bindings and state for a host
that dispatches actions instead of importing: without `refresh` from the file, with
`refresh: true` re-reading a stale cache, with `'force'` always, waiting up to two
Expand Down
25 changes: 18 additions & 7 deletions docs/adr/0004-shared-project-tool-registry.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,13 @@ Additive to the existing `createDevTools()` surface; nothing existing changes sh
whose catalog cannot be read keeps its `previous` tools and is listed as
`unavailable`; a removed connection loses its tools. No `expectedAccount` snapshot is
attached: a registered tool is bound to a saved connection, and the session for that
connection's backend is verified when the tool is called.
connection's backend is verified when the tool is called. Since 0.3.14 the whole read
runs within one budget (`budgetMs`, default 300 s, `DEFAULT_PROJECT_REFRESH_BUDGET_MS`):
a connection not read by then, like one whose read failed, stays in the catalog marked
`unavailable: { at, code, message }` with its earlier tools, so a scope whose
connections exist is never written empty and healthy, and the mark is in the file, where
a host whose process did not run the refresh still sees it. The first release wrote an
empty scope after a 773 s refresh and reported nothing; this is the correction.
- `createProjectToolCatalog({ file?, dispatch, staleMs?, notify?, disabled? })`: the
on-disk catalog (default `codex-tool-catalog.json` is renamed to a host-neutral
`project-tool-catalog.json` beside `mcp-connections.json`), with atomic writes, a lock
Expand All @@ -104,12 +110,17 @@ Additive to the existing `createDevTools()` surface; nothing existing changes sh
host's change announcement. It stores schemas and labels only; never credentials,
tool results or tokens. Because the file is shared by every host on the machine, a
refresh replaces only the connections in its scope (the backend, and the environment
when given) and carries the rest over, and `list()`/`state()` are scoped to the current
account's backend once a refresh has learned it from `auth-status`, so another
backend's cached connections stay out of a host's tool list. `refresh(force, { scope?,
waitMs? })` resolves to whether this process read and wrote the catalog; with `waitMs`
it waits for another process's lock instead of skipping, and reports `PROJECT_BUSY`
in its state when the wait runs out.
when given) and carries the rest over, and `list()`/`state()` are scoped to the host's
backend: the one given as `backend`, or resolved by `ready()` without any network
request the way `auth-status` resolves it (process environment, shared preferences,
default), or learned from a refresh. Until the backend is known a listing is empty,
never another backend's tools (the first release listed every cached scope on a fresh
server's first `tools/list`; a host now awaits `ready()` before answering it).
`refresh(force, { scope?, waitMs? })` resolves to whether this process read and wrote
the catalog; with `waitMs` it waits for another process's lock instead of skipping, and
reports `PROJECT_BUSY` in its state when the wait runs out. A refresh ends its
dispatcher's signal when it returns, so a read the budget left behind cannot keep a
socket or the lock.
- `mainSequenceStateDirectory(env)`: the one place that knows
`~/Library/Application Support/MainSequenceCLI`, `%APPDATA%\MainSequenceCLI` and
`~/.config/mainsequence`, used by the connection store and the catalog.
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@dev-mainsequence/devtools",
"version": "0.3.13",
"version": "0.3.14",
"description": "Shared MainSequence developer actions, project operations, MCP client and command runner",
"license": "MIT",
"engines": {
Expand Down
4 changes: 2 additions & 2 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@ export type { ActionData, DiscoveryResultMap, AgentDirectory, McpConnection, Mcp
export { mainSequenceStateDirectory } from './shared/stateDirectory';
export { projectToolName, isProjectToolName, projectToolConnection, projectToolConnectionLabel, projectToolDefinition, projectToolDefinitions, projectToolBinding, projectToolRegistration,
projectToolResult, projectToolTimeoutMs, readProjectToolCatalog, readProjectToolCatalogFile, projectToolCatalogPath, createProjectToolCatalog,
PROJECT_TOOL_PREFIX, MAX_PROJECT_TOOLS_PER_CONNECTION, PROJECT_TOOL_TIMEOUT_HINT, DEFAULT_PROJECT_REQUEST_TIMEOUT_MS, MAX_PROJECT_TOOL_TIMEOUT_MS } from './shared/projectTools';
PROJECT_TOOL_PREFIX, MAX_PROJECT_TOOLS_PER_CONNECTION, PROJECT_TOOL_TIMEOUT_HINT, DEFAULT_PROJECT_REQUEST_TIMEOUT_MS, MAX_PROJECT_TOOL_TIMEOUT_MS, DEFAULT_PROJECT_REFRESH_BUDGET_MS } from './shared/projectTools';
export type { ProjectToolBinding, ProjectToolConnection, ProjectToolCatalog, ProjectToolCatalogOptions, ProjectToolCatalogState, ProjectToolCatalogStore, ProjectToolCatalogView,
ProjectToolDefinition, ProjectToolDispatch, ProjectToolResult, ProjectToolScope } from './shared/projectTools';
ProjectToolDefinition, ProjectToolDispatch, ProjectToolResult, ProjectToolScope, ProjectToolUnavailable } from './shared/projectTools';
export { listEnvironments } from './shared/environments';
export type { EnvironmentSummary } from './shared/environments';
export { bindSessionAccount } from './shared/accountScope';
Expand Down
Loading
Loading