Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/personal-server/local/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ export function localServerNetwork(name: VanaNetworkName): LocalServerNetwork {
}

/** The pinned server release, matching runtime-pkg/package.json. */
export const PERSONAL_SERVER_VERSION = "1.31.0";
export const PERSONAL_SERVER_VERSION = "1.32.0";

export function localServerHome(): string {
return path.join(getVanaHome(), "cli", "personal-server");
Expand Down
7 changes: 7 additions & 0 deletions src/personal-server/local/runtime-pkg/derived-config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@
// the tunnel client, and how it lands on a persisted server.json. Kept apart
// from entry.mjs so it can be tested without starting a server.

// Lifetime of the grants the server signs itself for MCP connections (an
// agent connecting over OAuth, or a scope request approved with no live
// grant to inherit an expiry from): one year from signing. Needs
// personal-server-ts with `mcpGrantTtlSeconds`; an older server ignores the
// option and keeps signing perpetual grants.
export const MCP_GRANT_TTL_SECONDS = 365 * 24 * 3600;

function isPlainObject(value) {
return (
typeof value === "object" &&
Expand Down
9 changes: 8 additions & 1 deletion src/personal-server/local/runtime-pkg/entry.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,11 @@ import {
} from "@opendatalabs/personal-server-ts/node";
import { vanaWebMcpScopeRequestApprovalUrl } from "@opendatalabs/personal-server-ts-core/mcp";

import { applyDerived, derivedConfig } from "./derived-config.mjs";
import {
applyDerived,
derivedConfig,
MCP_GRANT_TTL_SECONDS,
} from "./derived-config.mjs";
import { startMcpApprovalPage } from "./mcp-approval.mjs";

const send = (message) => process.stdout.write(`${JSON.stringify(message)}\n`);
Expand Down Expand Up @@ -197,6 +201,9 @@ async function main() {
mcpScopeRequestApprovalUrl: vanaWebMcpScopeRequestApprovalUrl({
webOrigin: network.webOrigin,
}),
// MCP connection grants this server signs expire after a year instead
// of never. A live grant's expiry is always kept on a scope request.
mcpGrantTtlSeconds: MCP_GRANT_TTL_SECONDS,
configDefaults,
onStatus: (status) => process.stderr.write(`[status] ${status}\n`),
});
Expand Down
40 changes: 20 additions & 20 deletions src/personal-server/local/runtime-pkg/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions src/personal-server/local/runtime-pkg/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
"type": "module",
"description": "The Personal Server vana-cli runs on its own. Installed with npm ci from this lockfile so every install is the same.",
"dependencies": {
"@opendatalabs/personal-server-ts": "1.31.0",
"@opendatalabs/personal-server-ts-core": "1.31.0"
"@opendatalabs/personal-server-ts": "1.32.0",
"@opendatalabs/personal-server-ts-core": "1.32.0"
},
"allowScripts": {
"better-sqlite3@12.11.1": true,
Expand Down
17 changes: 17 additions & 0 deletions test/personal-server/derived-config.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { afterEach, describe, expect, it } from "vitest";
import {
applyDerived,
derivedConfig,
MCP_GRANT_TTL_SECONDS,
// @ts-expect-error - plain ESM module shipped to the server process
} from "../../src/personal-server/local/runtime-pkg/derived-config.mjs";
import { ensureRuntime } from "../../src/personal-server/local/runtime.js";
Expand Down Expand Up @@ -79,3 +80,19 @@ describe("ensureRuntime", () => {
}
});
});

describe("MCP grant lifetime", () => {
it("is one year, and entry.mjs hands it to the server", () => {
expect(MCP_GRANT_TTL_SECONDS).toBe(365 * 24 * 3600);
const entry = fs.readFileSync(
fileURLToPath(
new URL(
"../../src/personal-server/local/runtime-pkg/entry.mjs",
import.meta.url,
),
),
"utf8",
);
expect(entry).toMatch(/mcpGrantTtlSeconds: MCP_GRANT_TTL_SECONDS/);
});
});
Loading