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
6 changes: 3 additions & 3 deletions bun.lock

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

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
"@clerk/themes": "^2.4.19",
"@mcp-ui/server": "^5.10.0",
"@modelcontextprotocol/sdk": "1.26.0",
"@onkernel/sdk": "^0.60.0",
"@onkernel/sdk": "^0.78.0",
"@types/jsonwebtoken": "^9.0.10",
"@types/redis": "^4.0.11",
"builtin-modules": "^5.0.0",
Expand Down
8 changes: 4 additions & 4 deletions src/lib/mcp/responses.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ type JsonItemsResponseOptions<T, U = T> = {
note?: string;
};

type PaginatedJsonResponseOptions<T, U = T> = JsonItemsResponseOptions<T, U>;
type PaginatedJsonResponseOptions<T, U = T> = JsonItemsResponseOptions<T, U> & {
emptyText?: string;
};

type ItemsJsonResponseOptions<T, U = T> = JsonItemsResponseOptions<T, U> & {
emptyText?: string;
Expand Down Expand Up @@ -47,10 +49,8 @@ export function paginatedJsonResponse<T, U = T>(
page: PaginatedPage<T>,
options: PaginatedJsonResponseOptions<T, U> = {},
) {
const { mapItem, note } = options;
return itemsJsonResponse(page.getPaginatedItems(), {
mapItem,
note,
...options,
has_more: page.has_more,
next_offset: page.next_offset,
});
Expand Down
37 changes: 21 additions & 16 deletions src/lib/mcp/tools/browser-pools.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@ import { registerJsonResourceTemplate } from "@/lib/mcp/resource-templates";
import {
jsonResponse,
errorResponse,
paginatedJsonResponse,
textResponse,
toolErrorResponse,
} from "@/lib/mcp/responses";
import { paginationParams } from "@/lib/mcp/schemas";

type BrowserPoolCreateParams = Parameters<
KernelClient["browserPools"]["create"]
Expand All @@ -27,7 +29,10 @@ type BrowserPoolAcquireResponse = Awaited<
ReturnType<KernelClient["browserPools"]["acquire"]>
>;

type PoolConfigParams = BrowserCreateConfigParams & {
type PoolConfigParams = Omit<
BrowserCreateConfigParams,
"save_profile_changes"
> & {
size?: number;
name?: string;
headless?: boolean;
Expand Down Expand Up @@ -159,14 +164,17 @@ export function registerBrowserPoolCapabilities(server: McpServer) {
}

const client = createKernelClient(extra.authInfo.token);
const pools = await client.browserPools.list();
const pools = [];
for await (const pool of client.browserPools.list()) {
pools.push(pool);
}
return {
contents: [
{
uri: uri.toString(),
mimeType: "application/json",
text:
pools && pools.length > 0
pools.length > 0
? JSON.stringify(pools.map(summarizeBrowserPool), null, 2)
: "No browser pools found",
},
Expand Down Expand Up @@ -245,12 +253,6 @@ export function registerBrowserPoolCapabilities(server: McpServer) {
"(create, update) Profile ID to load into pool browsers. Cannot use with profile_name.",
)
.optional(),
save_profile_changes: z
.boolean()
.describe(
"(create, update) Save browser changes back to the selected profile when sessions end.",
)
.optional(),
proxy_id: z
.string()
.describe("(create, update) Proxy for pool browsers.")
Expand Down Expand Up @@ -335,6 +337,7 @@ export function registerBrowserPoolCapabilities(server: McpServer) {
.boolean()
.describe("(release) Reuse browser instance or recreate. Default true.")
.optional(),
...paginationParams,
},
{
title: "Manage Kernel browser pools",
Expand Down Expand Up @@ -391,13 +394,15 @@ export function registerBrowserPoolCapabilities(server: McpServer) {
});
}
case "list": {
const pools = (await client.browserPools.list()) ?? [];
return pools.length > 0
? jsonResponse({
items: pools.map(summarizeBrowserPool),
note: 'Use action "get" with id_or_name for full pool details.',
})
: textResponse("No browser pools found");
const page = await client.browserPools.list({
...(params.limit !== undefined && { limit: params.limit }),
...(params.offset !== undefined && { offset: params.offset }),
});
return paginatedJsonResponse(page, {
mapItem: summarizeBrowserPool,
note: 'Use action "get" with id_or_name for full pool details.',
emptyText: "No browser pools found",
});
}
case "get": {
if (!params.id_or_name)
Expand Down
10 changes: 8 additions & 2 deletions src/lib/mcp/tools/credential-providers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@ import { createKernelClient } from "@/lib/mcp/kernel-client";
import {
errorResponse,
jsonResponse,
paginatedJsonResponse,
textResponse,
toolErrorResponse,
} from "@/lib/mcp/responses";
import { paginationParams } from "@/lib/mcp/schemas";

export function registerCredentialProviderTools(server: McpServer) {
// manage_credential_providers -- Manage external credential providers
Expand All @@ -31,6 +33,7 @@ export function registerCredentialProviderTools(server: McpServer) {
"(get, update, delete, list_items, test) Credential provider ID.",
)
.optional(),
...paginationParams,
name: z
.string()
.describe("(create, update) Human-readable name (unique per org).")
Expand Down Expand Up @@ -80,8 +83,11 @@ export function registerCredentialProviderTools(server: McpServer) {
try {
switch (params.action) {
case "list": {
const providers = await client.credentialProviders.list();
return jsonResponse(providers);
const page = await client.credentialProviders.list({
...(params.limit !== undefined && { limit: params.limit }),
...(params.offset !== undefined && { offset: params.offset }),
});
return paginatedJsonResponse(page);
}
case "get": {
if (!params.id)
Expand Down
2 changes: 1 addition & 1 deletion src/lib/mcp/tools/credentials.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export function registerCredentialTools(server: McpServer) {
)
.optional(),
values: z
.record(z.string())
.record(z.string(), z.string())
.describe(
"(create, update) Field name to value mapping (e.g. username, password). On update, merged with existing values.",
)
Expand Down
13 changes: 8 additions & 5 deletions src/lib/mcp/tools/extensions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@ import { z } from "zod";
import { createKernelClient } from "@/lib/mcp/kernel-client";
import {
errorResponse,
itemsJsonResponse,
paginatedJsonResponse,
textResponse,
toolErrorResponse,
} from "@/lib/mcp/responses";
import { paginationParams } from "@/lib/mcp/schemas";

export function registerExtensionTools(server: McpServer) {
// manage_extensions -- List and delete browser extensions
Expand All @@ -19,6 +20,7 @@ export function registerExtensionTools(server: McpServer) {
.string()
.describe("(delete) Extension ID or name to delete.")
.optional(),
...paginationParams,
},
{
title: "Manage Kernel browser extensions",
Expand All @@ -34,10 +36,11 @@ export function registerExtensionTools(server: McpServer) {
try {
switch (params.action) {
case "list": {
const extensions = await client.extensions.list();
return itemsJsonResponse(extensions ?? [], {
has_more: false,
next_offset: null,
const page = await client.extensions.list({
...(params.limit !== undefined && { limit: params.limit }),
...(params.offset !== undefined && { offset: params.offset }),
});
return paginatedJsonResponse(page, {
emptyText: "No extensions found",
});
}
Expand Down
13 changes: 8 additions & 5 deletions src/lib/mcp/tools/proxies.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@ import { z } from "zod";
import { createKernelClient } from "@/lib/mcp/kernel-client";
import {
errorResponse,
itemsJsonResponse,
jsonResponse,
paginatedJsonResponse,
textResponse,
toolErrorResponse,
} from "@/lib/mcp/responses";
import { paginationParams } from "@/lib/mcp/schemas";

const httpUrlSchema = z
.string()
Expand Down Expand Up @@ -77,6 +78,7 @@ export function registerProxyTools(server: McpServer) {
.string()
.describe("(create, custom type) Auth password.")
.optional(),
...paginationParams,
},
{
title: "Manage Kernel proxy configurations",
Expand Down Expand Up @@ -134,10 +136,11 @@ export function registerProxyTools(server: McpServer) {
return jsonResponse(proxy);
}
case "list": {
const proxies = await client.proxies.list();
return itemsJsonResponse(proxies ?? [], {
has_more: false,
next_offset: null,
const page = await client.proxies.list({
...(params.limit !== undefined && { limit: params.limit }),
...(params.offset !== undefined && { offset: params.offset }),
});
return paginatedJsonResponse(page, {
emptyText: "No proxies found",
});
}
Expand Down
Loading