CLI
The synapse CLI ships with @nimblebrain/synapse. Run it with npx synapse.
It generates TypeScript types from your tool surface, previews an app locally, and
checks a running server against what each host requires.
synapse codegen
Section titled “synapse codegen”Generate TypeScript types from an app manifest, a running MCP server, or a
directory of JSON schemas. The codegen subcommand is required, and you pass at
least one source flag (--from-manifest, --from-server, or --from-schema).
| Flag | Argument | Description |
|---|---|---|
--from-manifest |
<path> |
Generate types from an app manifest JSON file |
--from-server |
<url> |
Generate types from a running MCP server’s tool list |
--from-schema |
<dir> |
Generate CRUD tool types from a directory of .schema.json files |
--out |
<path> |
Write the generated TypeScript to this file |
--app |
<name> |
Scope generation to a single app by name |
# From an app manifestnpx synapse codegen --from-manifest ./manifest.json --out src/generated/types.ts
# From a running MCP servernpx synapse codegen --from-server http://localhost:3000 --out src/generated/types.ts
# From a directory of .schema.json files (generates CRUD tool types)npx synapse codegen --from-schema ./schemas --out src/generated/types.tssynapse preview
Section titled “synapse preview”Serve the app in a local host shell so you can exercise the ext-apps handshake, theming, and tool calls without deploying to a host.
npx synapse previewsynapse check
Section titled “synapse check”Connect to a running MCP server over Streamable HTTP and check what a host sees of it: the UI resources and their metadata, the MCP Apps extension declaration, and the OAuth discovery surface a host signs in through.
npx synapse check --target claude,chatgpt https://example.com/mcp
# A server that requires auth: pass a bearer token to run the checks that need a sessionSYNAPSE_CHECK_TOKEN=... npx synapse check --target chatgpt https://example.com/mcp| Flag | Argument | Description |
|---|---|---|
--target |
<list> |
Comma-separated profiles: nimblebrain, claude, chatgpt |
--token |
<token> |
Bearer token for a server that requires auth. Defaults to $SYNAPSE_CHECK_TOKEN |
--json |
Print the report as JSON |
Every check runs once. Each target’s profile decides which checks count for it, and whether a failure is an error (the command exits non-zero) or a warning (reported; a requirement the host documents but is not known to enforce). A server that cannot be reached, or rejects the given token, exits non-zero without a report.
| Check | What it verifies | nimblebrain | claude | chatgpt |
|---|---|---|---|---|
extension-declared |
The server declares io.modelcontextprotocol/ui in capabilities.extensions |
warn | error | error |
ui-resource-mime |
Every ui:// resource is listed and served as text/html;profile=mcp-app |
error | error | error |
tool-resource-uri |
Some tool binds a UI through _meta.ui.resourceUri, and every binding reads |
error | error | error |
tool-ui-meta |
ui.visibility is a non-empty subset of model/app; no csp or permissions on a tool |
error | error | error |
resource-csp |
Every UI resource declares ui.csp as lists of origins |
— | warn | warn |
resource-openai-csp |
Every UI resource declares openai/widgetCSP, with ChatGPT’s connect_domains/resource_domains spelling |
— | — | warn |
resource-data-fonts |
No data: font in the HTML unless ui.csp.resourceDomains includes data: |
— | error | — |
resource-openai-data-fonts |
No data: font in the HTML unless openai/widgetCSP.resource_domains includes data: |
— | — | warn |
auth-challenge |
An unauthenticated request’s 401 carries resource_metadata in WWW-Authenticate |
warn | error | error |
auth-resource-metadata |
The protected-resource metadata’s resource equals the server URL exactly |
warn | error | error |
auth-issuer |
The first authorization server’s metadata issuer equals the advertised string exactly |
warn | warn | error |
tool-security-schemes |
Every tool declares securitySchemes when the server requires auth |
— | — | error |
The frame’s security policy is checked once per dialect. Claude and the
NimbleBrain host read the spec’s nested ui.csp. OpenAI documents ui.csp as
generally preferred for new UI and the sibling openai/widgetCSP as a legacy
compatibility key, still the only way to declare redirect_domains. Neither has
been observed to change what ChatGPT enforces: measured 2026-09-18 in developer
mode, a frame whose resource carried both ran under ChatGPT’s own default sandbox
policy. So both checks warn for chatgpt rather than fail. A server should
declare both.
The auth checks run only when the server answers an unauthenticated request with
401. When it does and no token is given, the checks that need a session are
skipped rather than failed. The URL is compared exactly, so pass the connector
URL a host is given, including or omitting a trailing slash as it does.
See also
Section titled “See also”- Package exports for the
@nimblebrain/synapse/codegenprogrammatic entry point.