configure()
Every shipped pack builds its tools at import, so from charter.packs.gmail import TOOLS works before anything is configured — schemas, llm_schema() and
to_json_schema() need no credential. The credential arrives afterwards,
through the pack’s configure().
A credential is resolved per request, not captured when the tool is built. That
is why
configure() reaches tools that already exist, and why a reference taken
before configuration keeps working after it. Calling a tool on a pack that has
none raises CredentialError naming both
the configure() call and the environment variable it would have accepted. It
fails locally, before the request.Bearer packs
gmail, gcalendar, gsheets, gdocs, gdrive, gforms, slack, github, notion.
CredentialProvider: a
StaticTokenProvider for a script, an
OAuth2Client for a process that stays up, a
SubjectProvider wrapping one of those per end user.
API-key packs
stripe, linear, firecrawl, granola. An empty key raises
CredentialError.
Shopify
shop is the subdomain — "my-store" for my-store.myshopify.com — and the
full domain or URL is accepted too. access_token is an Admin API access token.
Environment fallbacks
A pack with noconfigure() call falls back to a documented variable, read on
first use.
The bearer variables are read per call, so a sidecar that refreshes one is
picked up without a restart. The API-key variables are read at import.
This is the path the MCP entry point uses, which is why it needs
no configuration code. A raw access token expires in about an hour: for a server
that stays up, configure the pack with an
OAuth2Client in your own process instead.
Settings that tune behaviour
These change how a request is made rather than what it contains. All are factory parameters unless noted, and each can be overridden per tool.int
default:"20"
Request timeout in seconds. Per tool:
timeout_override.int
default:"10"
How dead a bearer token must be before the runtime refuses to send it. On
oauth_tool_factory only. This is a guard, not a refresh policy: keeping a
token fresh is the provider’s job, and OAuth2Client renews 90 seconds early
by default. Ten seconds covers clock skew and the request itself — refusing a
token the server still calls valid for a minute would be the runtime
overruling the server.Optional[Iterable[int]]
default:"{401}"
Which statuses raise
CredentialError rather than APIError. Declare
{401, 403} for an API that means “your token” by 403.Optional[CallSink]
default:"None"
Where finished
ToolCall records go. Declared on
the factory because observability belongs to the deployment, not to one
endpoint. Per tool: on_call_override.Optional[Dict[str, str]]
default:"None"
Headers sent verbatim on every request — an Azure
api-version, a
Notion-Version. Not case-converted, absent from the LLM schema, applied
after tool input so a schema field cannot overwrite them.Optional[Dict[str, Any]]
default:"None"
Query parameters sent verbatim on every request. Same three properties.
Optional[Dict[str, Any]]
default:"None"
Body keys sent verbatim. Per tool only: a constant in the body belongs to one
operation, the GraphQL query document being the case that motivated it.
KeyCase
default:"\"camel\", \"snake\", \"snake\""
How keys are spelled on the wire. Per tool:
body_case_override,
query_case_override, path_case_override. Per field:
Case. See
the cascade."json" | "form"
default:"\"json\""
"form" for application/x-www-form-urlencoded. Per tool:
body_format_override."repeat" | "bracket"
default:"\"repeat\""
How structured query values serialise. Factory-wide; there is no per-tool
override.
Logging
The library attaches aNullHandler to the charter logger and configures
nothing else for its host: emitting a record is a no-op until the application
opts in.
Enabling INFO also switches on payload measurement, because something is then
listening for the sizes.
Related
- MCP server — the entry point these variables feed
- Packs — what each pack configures
- Authorization servers — declaring the server behind an
OAuth2Client