What's new in Beacon 5.0
Beacon 5.0 was released on 21 October 2026 (NuGet version 5.0.0). Its headline is the MCP gateway: one package
that turns your own ASP.NET Core application into an MCP server, so Claude and other AI clients act as your signed-in
users through your own endpoints. Around it come test and verification tooling, a Claude Code plugin, LLM providers as
packages, and a lighter dependency graph.
Highlights
Section titled “Highlights”MCP gateway for your own application
Section titled “MCP gateway for your own application”Moberg.Beacon.Gateway embeds Beacon as the MCP server of an existing application. People connect Claude to
https://your-app/beacon/mcp and sign in with Microsoft Entra. A tool call then runs one of your endpoints as that
person, through your own authorization, and Beacon audits it. Your Markdown documents can ground the answers.
There are no data sources and no SQL. Read-only enforcement is pinned, and so is no content retention unless you set
RetainToolContent. /beacon/mcp answers 401/403 itself and never redirects to your sign-in.
builder.Services.AddBeaconMcpGateway(builder.Configuration, x =>{ x.ProjectName = "app"; x.Database(db => db.UsePostgreSql()); x.Entra(builder.Configuration.GetSection("AzureAd")); x.Users<AppMcpUsers>(); // your IMcpHostUserResolver: who a token is});// …app.UseBeaconMcpGateway();app.MapBeaconMcpGateway();An optional admin UI serves the MCP audit, the settings and your documents at /beacon to holders of one of your own
authorization policies, signed in through your own sign-in. → MCP gateway for your application
Endpoint tools, ready for real applications
Section titled “Endpoint tools, ready for real applications”[BeaconTool]works on handler classes whose framework copies class attributes into the endpoint, such as a Moberg Warp handler. On an MVC controller class it fails at startup and tells you to put the attribute on the action.BindFromCaller("userId", "app_user_id")fills the person’s own id from the caller and removes the argument from the tool’s schema. An agent cannot pass someone else’s id.- Tool calls run your
IExceptionHandlers, so a refusal reaches the agent as your own problem details. httpContext.User.IsBeaconMcpCall()tells you a request is an agent’s. You can then hold agents to less than the browser.AddBeaconMcp(x => …)chooses the built-in tools, turns saved-query tools off and replaces the server instructions.
→ Host endpoint tools, recipe: Expose an endpoint as a tool
Test it and verify it
Section titled “Test it and verify it”Moberg.Beacon.Testinghas Entra-shaped test tokens, an in-memory user resolver and a real MCP client over your test server (McpTestTokens,McpTestUsers,McpTestClient). Your tests then go through the bearer middleware, the caller mapping, the MCP filters, the audit and your endpoint’s own authorization.beacon-doctor(dotnet tool install -g Moberg.Beacon.Doctor) checks a deployed endpoint the way an MCP client sees it: the 401 challenge, the protected-resource metadata, the authorization server, PKCE andoffline_access. With--tokenit also runsinitializeandtools/list. It prints PASS/WARN/FAIL lines and exits non-zero on a failure.src/Beacon.SampleGatewayin the repository is a reference gateway host.
Built for coding agents
Section titled “Built for coding agents”- A Claude Code plugin ships in the repository:
/plugin marketplace add moberghr/beacon, then/plugin install beacon@moberg-beacon. → Build with AI - Cookbooks: recipes that run start to finish, each with a prompt you can hand to your agent. → Cookbooks
- New one-file bundles:
llms-mcp.txt,llms-cookbooks.txtandllms-gateway.txt, next tollms-integrate.txtandllms-full.txt.
LLM providers as packages
Section titled “LLM providers as packages”AddBeaconAI registers OpenAI, Azure OpenAI and Anthropic (Claude). AWS Bedrock moved to its own package,
Moberg.Beacon.AI.Bedrock, which you activate with AddBeaconBedrock(), so Moberg.Beacon.AI no longer depends on
the AWS SDK. The admin settings page lists only the providers you installed
(GET /beacon/api/admin-settings/llm-providers). A configured provider that is not installed leaves AI without a
provider: the host logs a warning, and AI calls fail with a message that names the package to add.
Local embeddings moved to their own package too: Moberg.Beacon.AI.Embeddings.Onnx, activated with
AddBeaconOnnxEmbeddings(). Without it, retrieval is keyword-based and Moberg.Beacon.AI carries no ONNX runtime.
Migration writers in the connectors, and a lighter build
Section titled “Migration writers in the connectors, and a lighter build”Data-migration writes moved out of Moberg.Beacon.Core into the destination’s connector, behind
IMigrationBulkWriter. PostgreSQL writes with binary COPY, SQL Server with SqlBulkCopy and MERGE, MySQL with
multi-row parameterised inserts, Upsert with ON DUPLICATE KEY UPDATE, and Truncate-Load. Every write, the clear and
the primary key lookup run on the run’s one connection and transaction, so a run is all-or-nothing on PostgreSQL and
SQL Server, and an Insert or Upsert run is all-or-nothing on MySQL InnoDB. The exception is a MySQL Truncate-Load:
TRUNCATE commits on its own, so a run that fails after the clear leaves the table empty. EFCore.BulkExtensions and Pomelo.EntityFrameworkCore.MySql
have left the build, and Moberg.Beacon.Core no longer brings the SQL Server EF Core provider with it.
Under the hood
Section titled “Under the hood”- Beacon’s admin standing comes from the stored user’s live roles, not from the session’s role claim (see the upgrade list). Demoting someone takes effect on their next request.
/beacon/mcpaccepts MCP credentials only: an API key or a mapped bearer token.- Every SQL gate request now carries a row-level security context. This is groundwork: 5.0 filters no rows, and the
lock
Beacon:RowSecurity:Enabledstays off (a host that sets it on does not start).
New packages
Section titled “New packages”| Package | What it is |
|---|---|
Moberg.Beacon.Gateway | The MCP gateway for your own application |
Moberg.Beacon.Testing | Test helpers for a gateway host’s MCP tools |
Moberg.Beacon.Doctor | The beacon-doctor .NET tool |
Moberg.Beacon.AI.Bedrock | The AWS Bedrock LLM provider, previously inside Moberg.Beacon.AI |
Moberg.Beacon.AI.Embeddings.Onnx | Local ONNX embeddings for semantic retrieval, previously inside Moberg.Beacon.AI |
Upgrade from 4.x
Section titled “Upgrade from 4.x”Upgrade every Moberg.Beacon.* package to 5.0.0 together, then go through this list. Most hosts need only the first
two items.
- Apply the new migration.
AddRowSecurityModeladds five tables in thebeaconschema and a column ondata_sources, on PostgreSQL and on SQL Server. A host that callsBeacon.Core.ServiceConfiguration.UseBeacon(app.Services, createSchema: true)applies it at startup. A host that migrates in a separate step can callBeaconPostgreSqlMigrator.MigrateAsync(...)orBeaconSqlServerMigrator.MigrateAsync(...)from it. → Metadata database - Bedrock users: add the package. Reference
Moberg.Beacon.AI.Bedrockand callservices.AddBeaconBedrock()(before or afterAddBeaconAI). Without them, Bedrock is not available and AI calls fail with “LLM provider Bedrock is not installed”. → AI providers - Semantic retrieval: add the embeddings package. Reference
Moberg.Beacon.AI.Embeddings.Onnxand callservices.AddBeaconOnnxEmbeddings()(before or afterAddBeaconAI).AddBeaconEmbeddings()is obsolete and no longer loads the model. Without the package, retrieval falls back to keywords; withBeacon:Embeddings:Enabledon, the host logs one warning the first time retrieval asks for embeddings. → AI providers - Migration targets: register the connector. A data-migration run writes through the destination’s connector,
so a PostgreSQL, SQL Server or MySQL target needs that connector package and its
Add<Engine>Connector()call. A run into an engine without one fails before Beacon decrypts the target’s credentials. If you run MySQL Truncate-Load jobs, keep a way to reload the table: a failed run leaves it empty. → Data migration - Central package management: raise your pins. If restore fails with
NU1109(“Detected package downgrade”), raise each pinned package to the version the message names (EF Core andMicrosoft.Extensions.*patches,ClosedXML). → Packages - No browser sessions on
/beacon/mcp. A signed-in browser session, Beacon’s or yours, now gets403there. MCP clients use an API key or a mapped Entra token. The MCP playground is not affected: it calls/beacon/api. → Connect AI clients - Hosts that own sign-in: grant Admin in Beacon. While Beacon manages users, Admin comes from the Beacon user’s
own roles. An identity-provider role named
Admin(an Entra app role, for example) no longer makes someone Beacon’s Admin: grant the Admin role to their Beacon user. Functional permissions mapped withBeacon:Authorization:IdpRolesare unchanged. Hosts without Beacon user management keep the claim. → User management - Hosts that use Core without the API or MCP packages: the request principal must be registered. Call
AddBeaconApiServices,AddBeaconCookieAuthenticationorAddBeaconMcp, or register your own withservices.UseRequestPrincipal<T>().IHttpContextAccessoralone no longer identifies the caller. → Host wiring - SQL Server provider no longer transitive.
Moberg.Beacon.Coreno longer referencesMicrosoft.EntityFrameworkCore.SqlServerorEFCore.BulkExtensions. A host on SQL Server already referencesMoberg.Beacon.Core.SqlServer. Add your own reference only if your own code used those packages through Beacon. The same goes forAWSSDK.BedrockRuntimeand the ONNX packages, whichMoberg.Beacon.AIno longer brings. - Code that calls Beacon’s internals:
SqlGateRequesttakes aRowSecurityargument, which you get fromIRowSecurityResolver.- The
LlmProviderFactory(accessor, logger)constructor is obsolete. Resolve the provider registrations from DI. Constants.Migration.MaxFailedRowsBeforeStopis gone.IMigrationBulkContextProvider,MigrationBulkContextFactoryandDynamicDbContextare removed withEFCore.BulkExtensions, andSqlServerDataTransferManagerandObjectDataReader<T>with the old SQL Server bulk path. Migration writes use the connectors’IMigrationBulkWriter.BedrockProvidermoved to theBeacon.AI.Bedrockassembly andIHostEndpointDispatchMiddlewaretoBeacon.MCP. Both keep their namespaces: recompile.SqlClientTransportInspectorhas an abstractRead(string)method, so a class of your own that derives from it must implement it.DatabaseAuthorizationProvider’s constructor takesIBeaconRequestPrincipal, and its(IUserManagementService)overload is gone.AuthenticationPathPrefixes.Matches(PathString)is gone: useBeaconRequestPaths.Matches.
Behaviour changes worth knowing
Section titled “Behaviour changes worth knowing”| Area | In 5.0 |
|---|---|
| MySQL migration runs | All-or-nothing on InnoDB. A run no longer ends as a partial success. A Truncate-Load that fails after the clear leaves the table empty. Upsert matches on any unique key and no longer needs the CREATE TEMPORARY TABLES privilege. |
| AI provider | Choosing a provider that needs an API key requires typing a key. Saving or testing a provider that is not installed is refused while AI is on. |
| Admin standing | A user who loses the Admin role loses Admin routes on their next request, not at the next session revalidation. |
| PostgreSQL and SQL Server migration runs | All-or-nothing: the writes and the key lookup share the run’s transaction, with no row-by-row fallback. An Upsert into a table without a primary key fails. An unqualified SQL Server table means dbo. |
| SQL Server migration Insert | Keeps source identity values and NULLs (writing identity values needs ALTER on the table) and checks CHECK and foreign-key constraints: a violating row fails the run. |
| XLSX attachments | Dates keep a date format per cell, DateOnly and DateTimeOffset are written as dates, and a report with no rows is an empty workbook instead of an error. |
After 5.0.0
Section titled “After 5.0.0”These changes are on main and ship in the next release after 5.0.0.
OpenTelemetry: the MCP SDK’s spans need AddBeaconMcpSdkTracing()
Section titled “OpenTelemetry: the MCP SDK’s spans need AddBeaconMcpSdkTracing()”AddBeaconInstrumentation() on the tracer provider no longer subscribes to the MCP SDK’s own tools/call spans
(source Experimental.ModelContextProtocol); it adds only Beacon’s "Beacon" source. A host that upgrades loses those
spans until it also calls AddBeaconMcpSdkTracing() on the same builder, which adds the source and clears the status
descriptions the SDK writes (they can carry an error result’s content). Do not add Experimental.ModelContextProtocol
yourself: that bypasses the scrubber. The meter extension is unchanged.
OpenAI and Azure OpenAI over plain HTTP
Section titled “OpenAI and Azure OpenAI over plain HTTP”OpenAI and Azure OpenAI now go over plain HTTP, as Claude already did, so Moberg.Beacon.AI no longer brings the
OpenAI, Azure.AI.OpenAI or Azure.Core packages. Requests keep the SDKs’ wire format and retry policy (up to three
retries on 408, 429 and 5xx, honouring Retry-After up to 60 seconds). Redirects are not followed, so an API key never
travels to a redirect target. Failures name the HTTP status and the provider’s error code, never the response body, and
the request queue does not resend a call that failed with a status, since the provider already retried it.
This also fixes Azure OpenAI, which failed on every call in 4.x and 5.0.0 with a MissingMethodException.
When you upgrade:
- Packages no longer transitive. If your own code used
OpenAI,Azure.AI.OpenAIorAzure.Corethrough Beacon, reference them yourself. - Code that builds providers itself:
OpenAiProviderandAzureOpenAiProviderkeep their constructors but are obsolete. Providers are built through theILlmProviderRegistrations thatAddBeaconAI()installs, and a host’s own registration for a built-in provider now wins whatever the call order.
Parameter placeholders have a shape
Section titled “Parameter placeholders have a shape”A step parameter’s placeholder must be {identifier}: letters, digits and underscore, starting with a letter or
underscore (so {1} is refused, although the editor’s auto-detect accepts digits). An empty placeholder is refused, it
must be distinct within the step, and a multi-step save now also requires every placeholder to occur in its step’s SQL.
Beacon checks it when a query is created or edited, when an AI actor proposes a change and when a query is newly exposed
as an MCP tool. Stored queries keep running as they are, and restoring an old version keeps its placeholders as stored,
also on an exposed tool. An already-exposed tool keeps running and can be edited or disabled; only newly exposing it
needs the shape. The next edit of a stored query asks for a valid placeholder.
When you upgrade:
- Hosts or scripts that create queries through the API: send
{name}placeholders. A bare word, a quoted or spaced placeholder is refused with the parameter’s name.
Stronger password hashes, checked user names
Section titled “Stronger password hashes, checked user names”Internal users’ passwords are hashed at 600,000 PBKDF2 iterations, and the count is stored in the hash. Existing hashes keep working and are upgraded at each user’s next successful password sign-in (Password hashes). Creating a user, and first-run setup, now trim the user name and e-mail address and refuse a user name outside 3 to 100 characters or with control characters, an e-mail address that is not one plain address, and (setup) a password confirmation that differs. Editing a user keeps a value sent back exactly as stored, and trims and checks only the fields that change.
When you upgrade:
- Rollback: an earlier version cannot read an upgraded hash. After a rollback, reset the passwords of internal users who signed in on this version.
- Scripts that create users through the API: send a user name of at least 3 characters and a plain e-mail address (or none).
Security headers and an origin check on Beacon’s routes
Section titled “Security headers and an origin check on Beacon’s routes”Beacon’s responses now carry X-Content-Type-Options, X-Frame-Options: DENY, Referrer-Policy: strict-origin and a
Permissions-Policy, and responses under /beacon a Content-Security-Policy that allows scripts, styles and workers from
Beacon’s own origin only and no framing. A new origin check looks at state-changing, realtime-hub and anonymous Beacon
requests and, in this release, only logs the ones from a foreign origin. UseBeaconAuthentication() adds both; your own
routes are untouched. See Security headers and the origin check.
When you upgrade:
- Hosts that frame Beacon or load it into another page’s content:
frame-ancestors 'none'andX-Frame-Options: DENYnow refuse it. Send your own policy on those responses, or setBeacon:Security:CsptoReportOnly. - Behind a proxy: set
Beacon:PublicBaseUrl(orBeacon:Security:AllowedOrigins), watch the log for the origin check’s warnings, then setBeacon:Security:OriginGuardtoEnforce. A later release is planned to makeEnforcethe default. - Optional: call
app.UseBeaconSecurityHeaders()beforeUseStaticFiles()so the UI’s files carry the headers too.
Retention by default
Section titled “Retention by default”A new data retention job can keep run history and logs bounded (see Data retention):
with Beacon:Retention:Days set it deletes rows of subscription runs, notifications, anomaly baselines and events, AI
actor runs and plans, migration runs, MCP eval runs and the execution log older than the window (90 days recommended; the MCP audit’s own window, 365 days
recommended). Beacon:Retention:ContentDays (30 recommended for regulated deployments) clears the SQL text, result
snapshots and model output of older rows, and Beacon:Retention:Locked refuses any window that keeps data forever.
Every window defaults to keep forever. The content lock
(RetainQueryContent off globally, Beacon:Mcp:ForceNoContentRetention) now also covers those stores outside MCP.
When you upgrade:
- Nothing is deleted on upgrade. Retention is off until you set a window; while none is set the host logs one
Information at startup (
RetentionUnconfigured). Set the recommended windows to start purging. - Schedule the job. Hosts with their own scheduler call
IDataRetentionService.RunAsyncdaily; the sample host runs it as the Warp jobdata-retention. - Content lock wider. With
RetainQueryContentoff globally orForceNoContentRetentionon, subscription result snapshots, the SQL text of runs and of the execution log, AI actor output and migration statements are no longer stored, and result snapshots stored before are cleared by the retention job.
Every declared foreign key becomes a relationship
Section titled “Every declared foreign key becomes a relationship”A column that takes part in more than one foreign key (for example tenant_id, referencing tenants on its own and
x together with x_id) now yields a relationship for each of them, so the composite key keeps both of its column
pairs. Before, Beacon kept one foreign key per column, and which one depended on the order the catalog returned. This
applies to SQL Server, Azure Synapse, PostgreSQL and MySQL sources. The column’s own foreign-key fields keep naming one
target: the foreign key whose constraint name sorts first.
When you upgrade:
- Data sources with overlapping foreign keys: more foreign-key relationships appear after the next metadata refresh. Nothing changes until a source is refreshed, and no relationship is removed.
Release notes
Section titled “Release notes”The full list of changes is on the 5.0.0.0 release.