You're clipped in, the season pass is in your pocket, and the whole mountain is open. Only one thing left to do: point it downhill and drop in 🏂
v1.2.0 was about where your apps are allowed to ride. v1.3.0 is about committing to the run. You'll be getting an app from your editor to production in one click, teaching the model new tricks, and finally seeing what your view is doing when it's running somewhere you can't open a console.
- Mixed auth, the easy way: one
authfield per tool to enable both public and signed-in tools on the same app - Deploy button: ship straight to Alpic from the DevTools, one click, live URL in seconds
- Skills over MCP: serve Skills from your server as first-class MCP resources
- View logs in terminal: stream a view's console straight to your dev-server terminal, particularly useful when debugging issues on mobile 📱
Point your tips down the fall line. Here's what's new 🏔️
Mixed auth, the easy way
v1.1.0 gave you mixed auth by hand: mcpAuthMetadataRouter, optionalBearerAuth, and a guard written into every protected handler. v1.2.0 gave you one-line branded providers, but they were all-or-nothing: point a server at an IdP and every tool sat behind sign-in.
Now the two meet. On any server with an oauth provider, each tool declares its own requirements with a single auth field, and the framework enforces it:
import { McpServer, descopeProvider } from "skybridge/server";
import * as z from "zod";
const server = new McpServer(
{ name: "my-app", version: "0.0.1" },
{ capabilities: {} },
{ oauth: await descopeProvider({ url: env.DESCOPE_MCP_SERVER_URL }) },
);
// Callable signed out — uses the token when one is present.
server.registerTool(
{
name: "search_public_docs",
description: "Search public documents. No sign-in required.",
inputSchema: { q: z.string() },
auth: { allowsAnonymous: true },
},
async ({ q }) => ({ content: await search(q) }),
);
// Requires sign-in with the listed scopes.
server.registerTool(
{
name: "search_private_docs",
description: "Search the user's private workspace.",
inputSchema: { q: z.string() },
auth: { scopes: ["search.read"] },
},
async ({ q }, extra) => ({ content: await search(q, { user: extra.authInfo }) }),
);See the new auth-descope-mixed example for a full walkthrough.
Deploy button
Until now, going from skybridge dev to a live URL meant leaving the DevTools and deploying from the CLI. We've made deploy accessible from the DevTools instead!
Hit it, sign in, and you're a few seconds away from a live deployed URL.
Skills over MCP
Skybridge can now serve Skills straight from your server as skill:// MCP resources. Drop a SKILL.md (plus any supporting files) under src/skills/, flip one option, and the server advertises the skills capability and serves each file over MCP:
const server = new McpServer(
{ name: "my-app", version: "0.0.1" },
{ capabilities: {} },
{ skills: true },
);Experimental while SEP-2640 is under review. Host support for Skills over MCP isn't widely available, as this feature hasn't officially landed in the MCP spec yet. We recommend experimenting with the feature on the Alpic playground, which supports Skills over MCP out of the box.
View logs in terminal
When your app runs inside the ChatGPT or Claude desktop or mobile app, there's no console to pop open, so your view's logs have been out of reach. Not anymore.
Skybridge now wires Vite's forwardConsole into the scaffold, so a view's console prints in the terminal running your dev server. Run through the tunnel, and the logs from an app running on your phone show up on your laptop.
No more guessing why a view breaks!
Changes
- feat(docs): add cursor and goose by @paulleseute in #911
- feat: add conformance app by @paulleseute in #889
- feat: enable workflow_dispatch on deploy-infra by @paulleseute in #914
- fix(build): skip vite build for view-less MCP servers by @syf2211 in #913
- feat(sky-440): Deploy button in devtools by @harijoe in #907
- Fix broken lockfile during merge by @harijoe in #915
- feat(core): add a --plain flag to dev for piping logs to a formatter by @pldesch-chift in #830
- chore(deps): bump all non-major dependencies + esbuild ^0.28 by @harijoe in #917
- chore(deps): enable renovate automerge, reduce release-age window to 3 days by @harijoe in #918
- Listed Descope as an auth provider to README by @mrunankpawar in #919
- docs: add Supabase Triplog example by @rodincave in #882
- fix(deps): update all non-major dependencies by @renovate[bot] in #635
- chore: rebase renovate PRs when behind main so automerge can arm by @harijoe in #922
- chore(deps): update actions/upload-pages-artifact action to v5 by @renovate[bot] in #926
- chore(deps): update actions/configure-pages action to v6 by @renovate[bot] in #925
- chore(deps): update actions/cache action to v6 by @renovate[bot] in #920
- chore(deps): update actions/checkout action to v7 by @renovate[bot] in #921
- chore: stop renovate bumping engines.node in published packages by @harijoe in #927
- chore(deps): update node.js to v24 by @renovate[bot] in #753
- chore(deps): update dependency typescript to v6 by @renovate[bot] in #928
- Added the token warning threshold of 4000 tokens by @Aayan-Ali-Hashim in #930
- feat(examples): add chatgpt-files by @paulleseute in #916
- fix(docs): dark mode example by @paulleseute in #933
- fix(devtools): stop widget e2e flake and surface flakes in CI by @harijoe in #931
- chore(deps): update all non-major dependencies to ^4.1.10 by @renovate[bot] in #940
- fix(deps): update all non-major dependencies to ^1.148.0 by @renovate[bot] in #944
- ci: run on v0 and v1 branches by @harijoe in #945
- fix(deps): update all non-major dependencies by @renovate[bot] in #946
- fix(devtools): deploy button QA fixes by @harijoe in #951
- feat: add descope.skybridge.tech CNAME for auth-descope example by @thleonard in #952
- chore(deps): update all non-major dependencies by @renovate[bot] in #948
- feat: add automation to conformance by @paulleseute in #932
- fix: conformance useRequestModal by @paulleseute in #959
- chore(deps): update actions/upload-artifact action to v7 by @renovate[bot] in #955
- chore(deps): update actions/checkout action to v7 by @renovate[bot] in #954
- chore(deps): replace dependency framer-motion with motion ^12.42.2 by @renovate[bot] in #958
- fix(deps): update all non-major dependencies by @renovate[bot] in #956
- chore(deps): update all non-major dependencies by @renovate[bot] in #961
- feat(core): serve Agent Skills over MCP (SEP-2640) by @harijoe in #939
- fix(deps): update all non-major dependencies to ^1.152.0 by @renovate[bot] in #962
- fix(deps): update all non-major dependencies by @renovate[bot] in #966
- chore(deps): update dependency postcss to ^8.5.17 by @renovate[bot] in #969
- fix: disable conformance by @paulleseute in #970
- feat(landing): add changelog page generated from github releases by @harijoe in #814
- docs(auth-workos): Fix README drift from example code by @gjtorikian in #968
- chore(deps): update all non-major dependencies by @renovate[bot] in #972
- chore(deps): update dependency tsx to ^4.23.1 by @renovate[bot] in #973
- fix(deps): update all non-major dependencies by @renovate[bot] in #975
- chore(deps): update dependency mintlify to ^4.2.694 by @renovate[bot] in #977
- fix(deps): update all non-major dependencies by @renovate[bot] in #980
- fix(deps): update all non-major dependencies by @renovate[bot] in #981
- feat(docs): add webmcp devtools setup by @paulleseute in #984
- fix(deps): update all non-major dependencies by @renovate[bot] in #982
- chore(deps): update all non-major dependencies by @renovate[bot] in #989
- feat: enable forwardConsole by @paulleseute in #990
- feat: mixed-auth on branded/custom providers by @harijoe in #938
Contributors
@Aayan-Ali-Hashim, @gjtorikian, @harijoe, @mrunankpawar, @paulleseute, @pldesch-chift, @renovate[bot], @rodincave, @syf2211, @thleonard