Release v0.24 – v0.26
v0.24 – v0.26 Release: Smarter Answers Questions About Itself, and Gets Ready for Production
October 17, 2026 · The Smarter Project
v0.21 to v0.23 published the Smarter API as a contract. v0.24 to v0.26, released on October 14 and 15, are about running a Smarter platform in public. Every platform now runs its own MCP server, with the Smarter Project’s code and documentation behind it. The API has rate limits. A production platform refuses to start without a real secret key. And a review of a real production deploy fixed a list of failures that the init job used to report as successes.
| Change | What it means for you |
|---|---|
| Smarter Project MCP server | Every platform serves the documentation and source code of all nine public smarter-sh repositories over MCP, for its own LLMClients, Claude Code or any other MCP client. |
| Two new LLMClients | smarter_developer explains and helps extend the platform. smarter_sdk_guide helps programmers call Smarter from the Python, Node.js and Go SDKs and the CLI. |
| API rate limiting | Every API, including the prompt APIs of deployed LLMClients, is limited per IP address and per user. Over the limit is HTTP 429. |
| SECRET_KEY is required | Outside local development, Smarter refuses to start without a real SECRET_KEY. |
| Production init fixes | The Helm init job fails when a step fails, converts the database to utf8mb4, and no longer leaves LLMClients stuck at DNS Not Verified. |
| Plugins are LLMTools | The console and docs call plugins LLMTools now. Manifests and kinds are unchanged. |
Ask Smarter about Smarter: the Smarter Project MCP server
The built-in smarter LLMClient answers questions about Smarter. It used to read the Smarter Project’s repositories through GitMCP, a third-party service that serves one repository per endpoint, ranks results loosely, and can change or disappear without notice.
Now every Smarter platform runs its own MCP server. It reads the documentation and source code of every public smarter-sh repository: the platform and its docs, the CLI, the Python, Node.js and Go SDKs, the VS Code extension, Smarter Chat, the quick start, and the cloud infrastructure. It’s a platform service, not a resource, so there is nothing to apply or configure.
| Endpoint | Reads |
|---|---|
/api/v1/mcp/smarter-project/ | Every repository. Each tool takes a repository argument. |
/api/v1/mcp/smarter-project/<repository>/ | One repository, such as smarter-cli. |
Any MCP client can use it. For example, Claude Code:
claude mcp add --transport http smarter-project https://<your-smarter>/api/v1/mcp/smarter-project/
The platform’s own built-in MCPClients use the MCP server of the platform that applies them. Each one is a manifest template, filled in with your platform’s domain:
apiVersion: smarter.sh/v1
kind: MCPClient
metadata:
name: smarter_project_github
description: Searches and reads the documentation and the source code of the Smarter platform.
version: 2.0.0
spec:
config:
transport: http
endpointUrl: ${environment_platform_scheme}://${environment_platform_domain}/api/v1/mcp/smarter-project/smarter/
authType: none
allowedTools:
- get_repository_overview
- search_documentation
- search_code
- read_file
- list_files
includeInstructions: true
timeout: 30
- Five read-only tools:
get_repository_overview,search_documentation,search_code,read_fileandlist_files. Results are Markdown, with links to the file on GitHub at the indexed commit, and to the page on docs.smarter.sh for documentation. - Fresh every hour. Celery Beat checks each repository’s latest commit hourly, which is one small request when nothing changed, and indexes it again only when it did.
initialize_platformqueues the first index. All nine repositories index in about 40 seconds. - Search without embeddings. Files are ranked in the database by how often each term occurs, weighted by how rare it is, with bonuses for matches in the path and the title. Quoted phrases and dotted identifiers count as single terms.
- Helpful errors. A tool asked for a missing file answers with the files the model may have meant.
- New built-in MCPClients and LLMClients.
smarter_projectreads every repository, and there are new clients for the Node.js and Go SDKs. The newsmarter_developerLLMClient is a staff engineer who explains the platform and helps extend it.smarter_sdk_guidehelps programmers call Smarter from the SDKs and the CLI.
Security
The server requires no authentication, because it serves public repositories and is read-only. It’s rate limited instead: each client IP address may send at most SMARTER_MCPSERVER_RATE_LIMIT requests a minute (1200 by default), counted in Redis so that every pod shares the count, and is answered 429 with Retry-After beyond that. The default is high because the platform’s own MCPClients connect from the platform’s own addresses.
MCPClient endpoints may now name a port. A loopback host such as http://localhost:9357 is allowed in local development only. In a deployed environment every endpoint must still be a public address, so an MCPClient can’t be used to reach the pod itself.
📖 Smarter Project MCP Server documentation
Rate limits on every API
Until v0.26, no Smarter API was rate limited, though the platform forwards billable LLM requests, and deployed LLMClients serve anonymous clients. Now:
- Anonymous clients are limited per IP address, 120 requests a minute by default (
SMARTER_THROTTLE_RATE_ANON). - Authenticated users are limited per user, 600 requests a minute by default (
SMARTER_THROTTLE_RATE_USER). - Deployed LLMClients are covered too. Their prompt APIs are plain Django views that Django REST Framework’s throttles never reached. They are now checked before the handler runs, so an over-limit prompt never reaches the LLM.
- One answer for every API: HTTP 429 with a
Retry-Afterheader. The Python and Node.js SDKs already retry 429s and honorRetry-After. - Shared across pods. The counters live in Redis.
Each rate takes Django REST Framework’s format, such as 300/minute, or none, off or disabled to turn it off. Any other value stops the platform at startup, so a typo can’t silently remove a limit.
A real SECRET_KEY, or no start
A missing SECRET_KEY used to log a warning. Every pod then generated its own random key, so sessions and signed tokens broke whenever a request reached another replica, or a pod restarted. Worse, the Helm chart’s SET-ME-IN-helm placeholder, which is published in this repository, would have been accepted as a real key.
Now, in every environment except local development, Smarter refuses to start unless SECRET_KEY is set to a real value. A missing key, the generated key and any SET-ME placeholder all count as not set. Local development still starts, with a random key and a warning. Docker image builds use a throwaway key for collectstatic only, which is never written to the image.
Alongside it, two documents were rewritten:
- API versioning (ADR-023). Each public interface has its own version, independent of the product’s: the REST API by URL path (
/api/vN/), manifests byapiVersion(smarter.sh/vN), and negotiated contracts such as Smarter Chat’s by an integer. A breaking change needs a deprecation window of at least two minor releases and six months, and removals only happen in a major release. The committed OpenAPI document and JSON Schemas are the record that reviews check. - SECURITY.md now has GitHub private vulnerability reporting as the preferred channel, response targets, supported versions, scope, safe harbor, and hardening notes for operators.
Production deploys that fail loudly
A review of a production run of the Helm init job found failures that it had reported as successes. v0.26 fixes each of them.
- The init job fails when a step fails. Each
manage.pystep printsFAILEDand is recorded, and the job exits non-zero at the end, so the Helm release is marked failed instead of passing silently. utf8mb4, everywhere. MariaDB rejected an emoji in a built-in LLMClient because the database wasutf8mb3. The bundled MariaDB and MySQL charts now start withutf8mb4, and a newmanage.py convert_database_charsetcommand (with--dry-run) converts every existing table. It handles the foreign keys that MariaDB won’t let it convert, and the init job runs it aftermigrate.- No more LLMClients stuck at DNS Not Verified. A deployed LLMClient whose domain is Not Verified or Failed is now deployed again. Nothing used to retry it.
- Built-in LLMClients that fail are reported.
deploy_builtin_llmclientsstill tries every manifest, then fails with the list of the ones that didn’t apply. - Longer system roles. The 2,048-character limit on an LLMClient’s
defaultSystemRoledated from 8k-context models, and Smarter’s ownsmarterLLMClient was over it. LLMClients and plugins now share one limit of 32,768 characters (about 8,000 tokens), with a warning above 8,192. - Re-applying a plugin keeps its prompt. Applying a changed plugin manifest could write the plugin’s old model and temperature back from the cache.
- Model lists for Anthropic and Google AI. Listing their models failed on authentication headers. Both use their own headers now, and Gemini’s model list is parsed.
- Tags update on apply. Applying a manifest never updated the tags of an existing LLMClient, Vectorsearch or Orchestrator.
- MCPClients forget the old server. When an MCPClient’s connection settings change, its discovered tools and server details are cleared until it connects to the new server. The console used to show the old server’s tools.
Plugins are now LLMTools
The Django app behind tool calling was called plugin, which described how it was built rather than what it is to a model: a tool that an LLM can call. It is now llmtool, and the web console’s sidebar, the console page, the React package and the documentation follow.
Nothing you use changes. The kinds (StaticPlugin, ApiPlugin, SqlPlugin, SkillPlugin, ImageSearchPlugin, WebsearchPlugin), your manifests, CLI commands and the console URL /plugin/ all stay the same. An existing database needs its tables renamed, which the upgrade does for you (see below).
Web console and API improvements
- The LLMClient list shows everything an LLMClient uses. Its Tools column lists its functions, plugins, MCPClients and guardrails, and the card view gains rows for MCPClients, guardrails, allowed origins and styles. The REST API’s LLMClients gain the same
mcpclients,guardrailsandtoolsfields, and the OpenAPI document with them. resourcesreports the right deployable kinds. The CLI’sresourcescommand said that only Prompt was deployable, which it isn’t, and that LLMClient, LLMHost, Vectorstore, SmarterAuthToken, User, CustomDomain and LLMHostCompute weren’t, though they are. Each kind’s answer now comes from its broker, and a test keeps them in step.- Built-in Providers open for every user. Opening the built-in
openaiProvider in the console answered 500, for two reasons: a plugin that used it stored a model that no longer exists, and users in other accounts couldn’t describe a built-in Provider. A broken dependent is now still listed, and still prevents deletion, but no longer breaks the page, and every user can describe the built-in Providers. - Error pages keep their status. A detail page whose describe failed showed a 500 with a traceback. It now shows a 400, 403, 404 or 500 page.
- Provider logos are absolute URLs on platforms that store files on disk instead of S3.
Upgrading
- Set
SECRET_KEYin every environment except local development, to a long random value, and the same value on every pod. A platform without one won’t start. Check the Helm values in particular: the chart’s default is a placeholder. - Optional settings:
SMARTER_THROTTLE_RATE_ANON(default120/minute),SMARTER_THROTTLE_RATE_USER(default600/minute) andSMARTER_MCPSERVER_RATE_LIMIT(default1200a minute,0disables it). A busy platform may need a higher MCP server limit, because its own MCPClients share its addresses. - The plugin app is renamed. A database created before v0.24 has
plugin_*tables. The Helm init job runs the newmanage.py rename_plugin_app_labelbeforemigrate, so Kubernetes deployments move on their next release. If you run Smarter another way, run it yourself beforemigrate. It’s idempotent, and does nothing on a new database. - Convert to
utf8mb4. The Helm init job runsmanage.py convert_database_charsetaftermigrate. Elsewhere, run it yourself, first with--dry-runto see which tables it will convert. - Helm releases can now fail. If an init step fails, the post-upgrade hook fails and Helm marks the release failed. Read the job’s log for the line that says
FAILED. - SDKs: update the Python, Node.js and Go SDKs to pick up the LLMClient’s new fields and the longer system role.
manage.py initialize_platformloads the new built-in MCPClients and LLMClients, and queues the first index of the Smarter Project repositories.
What’s next
The next post covers v0.27 to v0.29, which turn tool calling into installable extensions with a signed registry, and redesign the dashboard.
The full list of changes is in the v0.24, v0.25 and v0.26 changelogs. To try the release, start with the documentation, or browse the code on GitHub.
